<h1 class="section-title"><a name="基本类型" class="anchor" href="#基本类型"><span class="header-link"></span></a>基本类型</h1><div role="item"><p>程序的运行离不开基本的数据类型，如：numbers, strings, structures, boolean等。TypeScript支持所有你在JavaScript中会用到的数据类型的同时，还添加了便利的枚举类型（enumeration type）以供使用。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">For programs to be useful, we need to be able to work with some of the simplest units of data: numbers, strings, structures, boolean values, and the like. In TypeScript, we support much the same types as you would expected in JavaScript, with a convenient enumeration type thrown in to help things along.
</p></div><h2 class="section-title"><a name="布尔类型" class="anchor" href="#布尔类型"><span class="header-link"></span></a>布尔类型</h2><div role="item"><p>真/假值是最基本的数据类型，这种数据类型在JavaScript和TypeScript中（以及其他语言）称为布尔类型（boolean）。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The most basic datatype is the simple true/false value, which JavaScript and TypeScript (as well as other languages) call a &#39;boolean&#39; value.
</p></div><pre><code class="lang-js">var isDone: boolean = false;
</code></pre>
<h2 class="section-title"><a name="数字" class="anchor" href="#数字"><span class="header-link"></span></a>数字</h2><div role="item"><p>同JavaScript一样，TypeScript中数字都是浮点数。这些浮点数都被称作数字类型（number）。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">As in JavaScript, all numbers in TypeScript are floating point values. These floating point numbers get the type &#39;number&#39;.
</p></div><pre><code class="lang-js">var height: number = 6;
</code></pre>
<h2 class="section-title"><a name="字符串" class="anchor" href="#字符串"><span class="header-link"></span></a>字符串</h2><div role="item"><p>文本类型的数据是用JavaScript编写网页和服务器等程序的基础。同其他语言一样，我们使用字符串（string）来指代这些文本类型的数据。在TypeScript中，你可以像在JavaScript中那样，使用双引号（&quot;&quot;）或单引号（&#39;&#39;）来表示字符串。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Another fundamental part of creating programs in JavaScript for webpages and servers alike is working with textual data. As in other languages, we use the type &#39;string&#39; to refer to these textual datatypes. Just like JavaScript, TypeScript also uses the double quote (&quot;) or single quote (&#39;) to surround string data.
</p></div><pre><code class="lang-js">var name: string = &quot;bob&quot;;
name = &#39;smith&#39;;
</code></pre>
<h2 class="section-title"><a name="数组" class="anchor" href="#数组"><span class="header-link"></span></a>数组</h2><div role="item"><p>同JavaScript一样，TypeScript中我们也可以使用数组。我们可以使用两种不同的方式来写数组。第一种是在元素类型后面附上中括号（[]），来表示这种类型元素的数组：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">TypeScript, like JavaScript, allows you to work with arrays of values. Array types can be written in one of two ways. In the first, you use the type of the elements followed by &#39;[]&#39; to denote an array of that element type:
</p></div><pre><code class="lang-js">var list:number[] = [1, 2, 3];
</code></pre>
<div role="item"><p>第二种方式是使用泛型数组类型，形式如Array<elemType>：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The second way uses a generic array type, Array<elemType>:
</p></div><pre><code class="lang-js">var list:Array&lt;number&gt; = [1, 2, 3];
</code></pre>
<h2 class="section-title"><a name="枚举" class="anchor" href="#枚举"><span class="header-link"></span></a>枚举</h2><div role="item"><p>TypeScript拓展了JavaScript原生的标准数据类型集，增加了枚举类型（enum）。枚举是一种很有用的数据类型，就像C#等语言中一样，它提供了一种给数字类型的值，设置易于辨别的名字的方法。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">A helpful addition to the standard set of datatypes from JavaScript is the &#39;enum&#39;. Like languages like C#, an enum is a way of giving more friendly names to sets of numeric values.
</p></div><pre><code class="lang-js">enum Color {Red, Green, Blue};
var c: Color = Color.Green;
</code></pre>
<div role="item"><p>在默认情况下，枚举类型会从数字0开始标记它的元素。我们可以通过人为地设置元素的数值来改变默认值。例如，上面的例子我们可以设置成从1开始计数：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">By default, enums begin numbering their members starting at 0. You can change this by manually setting the value of one its members. For example, we can start the previous example at 1 instead of 0:
</p></div><pre><code class="lang-js">enum Color {Red = 1, Green, Blue};
var c: Color = Color.Green;
</code></pre>
<div role="item"><p>我们甚至可以给所有的枚举元素设置数值：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Or, even manually set all the values in the enum:
</p></div><pre><code class="lang-js">enum Color {Red = 1, Green = 2, Blue = 4};
var c: Color = Color.Green;
</code></pre>
<div role="item"><p>枚举类型有一个便捷特性，我们也可以直接用数值来查找其对应的枚举元素的名称。举例来说，如果我们有一个值为2,但我们不确定这个数值对应枚举类型中的哪个元素，那我们可以直接查找这个数值对应的名称：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">A handy feature of enums is that you can also go from a numeric value to the name of that value in the enum. For example, if we had the value 2 but weren&#39;t sure which that mapped to in the Color enum above, we could look up the corresponding name:
</p></div><pre><code class="lang-js">enum Color {Red = 1, Green, Blue};
var colorName: string = Color[2];

alert(colorName);
</code></pre>
<h2 class="section-title"><a name="Any" class="anchor" href="#Any"><span class="header-link"></span></a>Any</h2><div role="item"><p>当我们编写应用时，我们可能会需要描述一些类型不明确的变量。因为这些变量的值可能来源于一些动态的内容，如用户或第三方提供的库。在这种情况下，我们需要略过对这些变量进行的类型检查，让它们直接通过编译时的检查。为了实现这一目的，我们可以把它们标识为&#39;any&#39;类型：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">We may need to describe the type of variables that we may not know when we are writing the application. These values may come from dynamic content, eg from the user or 3rd party library. In these cases, we want to opt-out of type-checking and let the values pass through compile-time checks. To do so, we label these with the &#39;any&#39; type:
</p></div><pre><code class="lang-js">var notSure: any = 4;
notSure = &quot;maybe a string instead&quot;;
notSure = false; // okay, definitely a boolean
</code></pre>
<div role="item"><p>使用&#39;any&#39;类型是处理我们已有的JavaScript代码的一种强大的方式。我们可以用它来逐渐增加或减少在编译过程中的类型检查。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The &#39;any&#39; type is a powerful way to work with existing JavaScript, allowing you to gradually opt-in and opt-out of type-checking during compilation.
</p></div><div role="item"><p>当我们知道一个类型的部分数据类型，却又不确定所有的数据类型时，使用&#39;any&#39;可以为我们提供不少方便。比如你有一个数组，但是这个数组中的元素属于不同的数据类型，那你可以这么做：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The &#39;any&#39; type is also handy if you know some part of the type, but perhaps not all of it. For example, you may have an array but the array has a mix of different types:
</p></div><pre><code class="lang-js">var list:any[] = [1, true, &quot;free&quot;];

list[1] = 100;
</code></pre>
<h2 class="section-title"><a name="Void" class="anchor" href="#Void"><span class="header-link"></span></a>Void</h2><div role="item"><p>与&#39;any&#39;对应的数据类型是&#39;void&#39;，它代表缺省类型。没有返回值的函数就可以认为是&#39;void&#39;类型：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Perhaps the opposite in some ways to &#39;any&#39; is &#39;void&#39;, the absence of having any type at all. You may commonly see this as the return type of functions that do not return a value:
</p></div><pre><code class="lang-js">function warnUser(): void {
    alert(&quot;This is my warning message&quot;);
}
</code></pre>
<hr>
<h1 class="section-title"><a name="接口" class="anchor" href="#接口"><span class="header-link"></span></a>接口</h1><div role="item"><p>TypeScript的核心原则之一，是类型检查会集中关注数据的“结构”（shape）。这一行为有时被称作“鸭子类型”（duck typing）或“结构子类型化”（structural subtyping）。在TypeScript中，接口起到了为这些数据类型命名的作用，同时接口也是定义你代码之间的关系，或你的代码和其他项目代码之间关系的有效方法。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">One of TypeScript&#39;s core principles is that type-checking focuses on the &#39;shape&#39; that values have. This is sometimes called &quot;duck typing&quot; or &quot;structural subtyping&quot;. In TypeScript, interfaces fill the role of naming these types, and are a powerful way of defining contracts within your code as well as contracts with code outside of your project.
</p></div><h2 class="section-title"><a name="我们的第一个接口" class="anchor" href="#我们的第一个接口"><span class="header-link"></span></a>我们的第一个接口</h2><div role="item"><p>让我们来看看下面这个简单的例子，来了解接口是如何工作的：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The easiest way to see how interfaces work is to start with a simple example:
</p></div><pre><code class="lang-js">function printLabel(labelledObj: {label: string}) {
  console.log(labelledObj.label);
}

var myObj = {size: 10, label: &quot;Size 10 Object&quot;};
printLabel(myObj);
</code></pre>
<div role="item"><p>类型检查器会检查&#39;printLabel&#39;的调用。其中&#39;printLabel&#39;方法有一个参数，我们需要给这个参数传入一个带有名为&#39;label&#39;的字符串类型属性的对象。注意我们传入的这个对象实际上不只有&#39;label&#39;属性，但编译器只检查那些指定的属性，查看它们的类型是否相符。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The type-checker checks the call to &#39;printLabel&#39;. The &#39;printLabel&#39; function has a single parameter that requires that the object passed in has a property called &#39;label&#39; of type string. Notice that our object actually has more properties than this, but the compiler only checks to that at least the ones required are present and match the types required.
</p></div><div role="item"><p>让我们重写上面的例子，这次我们将使用接口来描述参数的需求，即传入的对象要有字符串类型的label属性。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">We can write the same example again, this time using an interface to describe the requirement of having the &#39;label&#39; property that is a string:
</p></div><pre><code class="lang-js">interface LabelledValue {
  label: string;
}

function printLabel(labelledObj: LabelledValue) {
  console.log(labelledObj.label);
}

var myObj = {size: 10, label: &quot;Size 10 Object&quot;};
printLabel(myObj);
</code></pre>
<div role="item"><p>我们可以用这个名为&#39;LabelledValue&#39;的接口来描述我们前面例子中的需求。它仍旧表示需要有一个名为&#39;label&#39;的字符串属性。值得注意的是，与其他编程语言不同，我们不需要明确地说
传给&#39;printLabel&#39;的对象实现了这个接口。这里只关注数据的“结构”。只要我们传给函数的对象满足指定的需求，那这个对象就是合法的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The interface &#39;LabelledValue&#39; is a name we can now use to describe the requirement in the previous example. It still represents having a single property called &#39;label&#39; that is of type string. Notice we didn&#39;t have to explicitly say that the object we pass to &#39;printLabel&#39; implements this interface like we might have to in other languages. Here, it&#39;s only the shape that matters. If the object we pass to the function meets the requirements listed, then it&#39;s allowed.
</p></div><div role="item"><p>必须指出的是，类型检查器并不要求这些属性遵循一定的顺序。只要接口要求的属性存在，并符合类型即可。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">It&#39;s worth pointing out that the type-checker does not require that these properties come in any sort of order, only that the properties the interface requires are present and have the required type.
</p></div><h2 class="section-title"><a name="可选属性（Optional Properties）" class="anchor" href="#可选属性（Optional Properties）"><span class="header-link"></span></a>可选属性（Optional Properties）</h2><div role="item"><p>接口中的属性并不都是必要的。在遵循一定的条件时，有些属性甚至可以不存在。在创建“option bags”这样的模式时，用户传给函数作为参数的对象，往往只包含部分属性在里面。在这种情况下，可选属性就显得很有用了。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Not all properties of an interface may be required. Some exist under certain conditions or may not be there at all. These optional properties are popular when creating patterns like &quot;option bags&quot; where the user passes an object to a function that only has a couple properties filled in.
</p></div><div role="item"><p>下面是这种模式的一个例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Here&#39;s as example of this pattern:
</p></div><pre><code class="lang-js">interface SquareConfig {
  color?: string;
  width?: number;
}

function createSquare(config: SquareConfig): {color: string; area: number} {
  var newSquare = {color: &quot;white&quot;, area: 100};
  if (config.color) {
    newSquare.color = config.color;
  }
  if (config.width) {
    newSquare.area = config.width * config.width;
  }
  return newSquare;
}

var mySquare = createSquare({color: &quot;black&quot;});
</code></pre>
<div role="item"><p>除了在声明可选属性时需要加上&#39;?&#39;作为标识以外，带有可选属性的接口的写法与其他接口相似。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Interfaces with optional properties are written similar to other interfaces, which each optional property denoted with a &#39;?&#39; as part of the property declaration.
</p></div><div role="item"><p>使用可选属性的优势在于，我们可以在描述可能存在的属性的同时，捕捉那些我们不希望存在的属性。举例来说，如果我们错误地拼写了传给&#39;createSquare&#39;方法的属性名的话，就会有一条错误信息提示我们：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The advantage of optional properties is that you can describe these possibly available properties while still also catching properties that you know are not expected to be available. For example, had we mistyped the name of the property we passed to &#39;createSquare&#39;, we would get an error message letting us know:
</p></div><pre><code class="lang-js">interface SquareConfig {
  color?: string;
  width?: number;
}

function createSquare(config: SquareConfig): {color: string; area: number} {
  var newSquare = {color: &quot;white&quot;, area: 100};
  if (config.color) {
    newSquare.color = config.collor;  // Type-checker can catch the mistyped name here
  }
  if (config.width) {
    newSquare.area = config.width * config.width;
  }
  return newSquare;
}

var mySquare = createSquare({color: &quot;black&quot;});
</code></pre>
<h2 class="section-title"><a name="函数类型" class="anchor" href="#函数类型"><span class="header-link"></span></a>函数类型</h2><div role="item"><p>接口可以描述各式各样的JavaScript对象。然而我们除了用接口来描述一个对象的属性以外，也可以用它来描述函数类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Interfaces are capable of describing the wide range of shapes that JavaScript objects can take. In addition to describing an object with properties, interfaces are also capable of describing function types.
</p></div><div role="item"><p>我们需要给接口一个调用标记来描述函数类型。它看起来就像是只有参数列表和返回类型的函数的定义。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To describe a function type with an interface, we give the interface a call signature. This is like a function declaration with only the parameter list and return type given.
</p></div><pre><code class="lang-js">interface SearchFunc {
  (source: string, subString: string): boolean;
}
</code></pre>
<div role="item"><p>定义好了这个接口以后，我们就可以像使用其他接口一样使用这个函数类型接口。下面展示了我们要如何创建一个函数类型变量并给它赋值一个同样类型的函数值。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Once defined, we can use this function type interface like we would other interfaces. Here, we show how you can create a variable of a function type and assign it a function value of the same type.
</p></div><pre><code class="lang-js">var mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
  var result = source.search(subString);
  if (result == -1) {
    return false;
  }
  else {
    return true;
  }
}
</code></pre>
<div role="item"><p>为了能正确地对函数类型进行类型检查，我们允许参数名称与接口不一致。就是说上面的例子也可以这么写：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">For function types to correctly type-check, the name of the parameters do not need to match. We could have, for example, written the above example like this:
</p></div><pre><code class="lang-js">var mySearch: SearchFunc;
mySearch = function(src: string, sub: string) {
  var result = src.search(sub);
  if (result == -1) {
    return false;
  }
  else {
    return true;
  }
}
</code></pre>
<div role="item"><p>在对函数的参数进行类型检查时，同一时间我们只会对一个参数进行类型检查，检查在接口对应位置上的参数的类型与其是否一致。而我们也会对函数表达式的返回类型进行检查（这里是true和false）。如果这里函数返回的是数字或字符串，那类型检查器就会警告我们返回的类型与SearchFunc接口不相符。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Function parameters are checked one at a time, with the type in each corresponding parameter position checked against each other. Here, also, the return type of our function expression is implied by the values it returns (here false and true). Had the function expression returned numbers or strings, the type-checker would have warned us that return type doesn&#39;t match the return type described in the SearchFunc interface.
</p></div><h2 class="section-title"><a name="数组类型" class="anchor" href="#数组类型"><span class="header-link"></span></a>数组类型</h2><div role="item"><p>我们也可以用接口来描述数组类型，它的声明方式与函数类型相似。数组类型会有一个&#39;index&#39;类型，我们用它来表示数组索引（数组下标）的类型。这样我们也需要索引所对应的返回值的类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Similarly to how we can use interfaces to describe function types, we can also describe array types. Array types have an &#39;index&#39; type that describes the types allowed to index the object, along with the corresponding return type for accessing the index.
</p></div><pre><code class="lang-js">interface StringArray {
  [index: number]: string;
}

var myArray: StringArray;
myArray = [&quot;Bob&quot;, &quot;Fred&quot;];
</code></pre>
<div role="item"><p>TypeScript支持两种索引类型：string和number。同时使用这两种类型的索引也是可能的，只要我们保证数字类型的索引所对应的值的类型，必须是字符串索引对应的值的类型的子类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">There are two types of supported index types: string and number. It is possible to support both types of index, with the restriction that the type returned from the numeric index must be a subtype of the type returned from the string index.
</p></div><div role="item"><p>虽然索引标识是描述数组和字典类型的数据的好方法，它同时也会强迫其他所有属性都与索引的返回类型相同。在下面的例子中，&#39;length&#39;属性的类型不符合索引的返回类型，这会导致类型检查抛出错误：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">While index signatures are a powerful way to describe the array and &#39;dictionary&#39; pattern, they also enforce that all properties match their return type. In this example, the property does not match the more general index, and the type-checker gives an error:
</p></div><pre><code class="lang-js">interface Dictionary {
  [index: string]: string;
  length: number;    // error, the type of &#39;length&#39; is not a subtype of the indexer
}
</code></pre>
<h2 class="section-title"><a name="类的类型" class="anchor" href="#类的类型"><span class="header-link"></span></a>类的类型</h2><h3 class="section-title"><a name="实现一个接口" class="anchor" href="#实现一个接口"><span class="header-link"></span></a>实现一个接口</h3><div role="item"><p>在C#和Java中，让一个类符合某种特定的约定，是一种很常见的接口的使用方式。在TypeScript中我们也可以这样使用接口。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">One of the most common uses of interfaces in languages like C# and Java, that of explicitly enforcing that a class meets a particular contract, is also possible in TypeScript.
</p></div><pre><code class="lang-js">interface ClockInterface {
    currentTime: Date;
}

class Clock implements ClockInterface  {
    currentTime: Date;
    constructor(h: number, m: number) { }
}
</code></pre>
<div role="item"><p>我们可以在一个接口中描述一个类需要实现的方法。就像下面的例子中的&#39;setTime&#39;方法：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">You can also describe methods in an interface that are implemented in the class, as we do with &#39;setTime&#39; in the below example:
</p></div><pre><code class="lang-js">interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);
}

class Clock implements ClockInterface  {
    currentTime: Date;
    setTime(d: Date) {
        this.currentTime = d;
    }
    constructor(h: number, m: number) { }
}
</code></pre>
<div role="item"><p>接口只能描述类的公共部分，而不关注私有部分。这种机制不允许我们通过接口来检查一个类的实例的私有部分。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Interfaces describe the public side of the class, rather than both the public and private side. This prohibits you from using them to check that a class also has particular types for the private side of the class instance.
</p></div><h3 class="section-title"><a name="类中的静态部分和实例部分的区别" class="anchor" href="#类中的静态部分和实例部分的区别"><span class="header-link"></span></a>类中的静态部分和实例部分的区别</h3><div role="item"><p>当使用类和接口时，我们应该要记得一个类有静态部分和实例特有的部分。你可能注意到了，如果创建一个带有构造函数标记的接口，并尝试创建一个类来实现这个接口的话，我们会收到个错误：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When working with classes and interfaces, it helps to keep in mind that a class has two types: the type of the static side and the type of the instance side. You may notice that if you create an interface with a construct signature and try to create a class that implements this interface you get an error:
</p></div><pre><code class="lang-js">interface ClockInterface {
    new (hour: number, minute: number);
}

class Clock implements ClockInterface  {
    currentTime: Date;
    constructor(h: number, m: number) { }
}
</code></pre>
<div role="item"><p>这是因为当一个类实现一个接口时，只有实例的部分会被进行检查。构造函数属于静态的部分，它并不在检查的范围之内。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">This is because when a class implements an interface, only the instance side of the class is checked. Since the constructor sits in the static side, it is not included in this check.
</p></div><div role="item"><p>对应地，我们应该直接检查类的静态部分。就像在下面的例子中，我直接检查类本身：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Instead, you would need to work with the &#39;static&#39; side of the class directly. In this example, we work with the class directly:
</p></div><pre><code class="lang-js">interface ClockStatic {
    new (hour: number, minute: number);
}

class Clock  {
    currentTime: Date;
    constructor(h: number, m: number) { }
}

var cs: ClockStatic = Clock;
var newClock = new cs(7, 30);
</code></pre>
<h2 class="section-title"><a name="扩展接口" class="anchor" href="#扩展接口"><span class="header-link"></span></a>扩展接口</h2><div role="item"><p>同类一样，接口也可以相互扩展。扩展机制负责将一个接口中的成员拷贝到另一个接口中，这意味着我们可以根据自己的意愿把接口分离成可重用的组件。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Like classes, interfaces can extend each other. This handles the task of copying the members of one interface into another, allowing you more freedom in how you separate your interfaces into reusable components.
</p></div><pre><code class="lang-js">interface Shape {
    color: string;
}

interface Square extends Shape {
    sideLength: number;
}

var square = &lt;Square&gt;{};
square.color = &quot;blue&quot;;
square.sideLength = 10;
</code></pre>
<div role="item"><p>一个接口可以扩展多个接口，从而成为多接口的组合。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">An interface can extend multiple interfaces, creating a combination of all of the interfaces.
</p></div><pre><code class="lang-js">interface Shape {
    color: string;
}

interface PenStroke {
    penWidth: number;
}

interface Square extends Shape, PenStroke {
    sideLength: number;
}

var square = &lt;Square&gt;{};
square.color = &quot;blue&quot;;
square.sideLength = 10;
square.penWidth = 5.0;
</code></pre>
<h2 class="section-title"><a name="混合类型（Hybrid Types）" class="anchor" href="#混合类型（Hybrid Types）"><span class="header-link"></span></a>混合类型（Hybrid Types）</h2><div role="item"><p>就像我们之前提到过的，接口可以描述现实中JavaScript所能表现的丰富的数据类型。由于JavaScript动态、灵活的特性，我们有时可能会碰到需要综合使用前面描述的接口的使用方法，来处理一个对象的情景。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">As we mentioned earlier, interfaces can describe the rich types present in real world JavaScript. Because of JavaScript&#39;s dynamic and flexible nature, you may occasionally encounter an object that works as a combination of some of the types described above.
</p></div><div role="item"><p>举个例子，一个带有额外属性的函数：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">One such example is an object that acts as both a function and an object, with additional properties:
</p></div><pre><code class="lang-js">interface Counter {
    (start: number): string;
    interval: number;
    reset(): void;
}

var c: Counter;
c(10);
c.reset();
c.interval = 5.0;
</code></pre>
<div role="item"><p>当同第三方JavaScript代码进行交互时，我们可能就需要使用上面的模式，来完整地描述一个数据的类型和结构。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When interacting with 3rd-party JavaScript, you may need to use patterns like the above to fully-describe the shape of the type.
</p></div><hr>
<h1 class="section-title"><a name="类" class="anchor" href="#类"><span class="header-link"></span></a>类</h1><div role="item"><p>传统的JavaScript主要用函数和原型继承作为构建可重用部件的基本方法。然而这对于习惯面向对象方法的程序员来说有些别扭。从下一个版本的JavaScript，即ECMAScript 6开始，JavaScript程序员将可以用基于类的面向对象来构建应用，而TypeScript则允许开发者现在就使用这些新技术。TypeScript将它们编译成可在主流浏览器和平台上运行的JavaScript，从而使得开发者不必等待下一个版本的JavaScript。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Traditional JavaScript focuses on functions and prototype-based inheritance as the basic means of building up reusable components, but this may feel a bit awkward to programmers more comfortable with an object-oriented approach, where classes inherit functionality and objects are built from these classes. Starting with ECMAScript 6, the next version of JavaScript, JavaScript programmers will be able to build their applications using this object-oriented class-based approach. In TypeScript, we allow developers to use these techniques now, and compile them down to JavaScript that works across all major browsers and platforms, without having to wait for the next version of JavaScript.
</p></div><h2 class="section-title"><a name="类" class="anchor" href="#类"><span class="header-link"></span></a>类</h2><div role="item"><p>让我们来看类的一个简单例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Let&#39;s take a look at a simple class-based example:
</p></div><pre><code class="lang-js">class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return &quot;Hello, &quot; + this.greeting;
    }
}

var greeter = new Greeter(&quot;world&quot;);
</code></pre>
<div role="item"><p>如果你曾经使用过C#或Java，那你应该对上面的语法很熟悉。我们声明了一个有三个成员的类&#39;Greeter&#39;，这三个成员分别为&#39;greeting&#39;属性、构造函数和&#39;greet&#39;方法。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The syntax should look very familiar if you&#39;ve used C# or Java before. We declare a new class &#39;Greeter&#39;. This class has three members, a property called &#39;greeting&#39;, a constructor, and a method &#39;greet&#39;. 
</p></div><div role="item"><p>你会注意到当我们在类中使用某个成员时，我们使用了&#39;this.&#39;前缀。这表明它是对类成员的一次访问。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">You&#39;ll notice that in the class when we refer to one of the members of the class we prepend &#39;this.&#39;. This denotes that it&#39;s a member access.
</p></div><div role="item"><p>代码的最后一行，我们用&#39;new&#39;操作符构建了一个Greeter类的实例。构造过程是：调用我们先前定义的构造函数，创建了一个Greeter类型的新对象，执行构造函数初始化这个对象。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In the last line we construct an instance of the Greeter class using &#39;new&#39;. This calls into the constructor we defined earlier, creating a new object with the Greeter shape, and running the constructor to initialize it.
</p></div><h2 class="section-title"><a name="继承" class="anchor" href="#继承"><span class="header-link"></span></a>继承</h2><div role="item"><p>我们可以在TypeScript中使用常见的面向对象模式。而在使用类的编程中，最基本的一个模式便是通过继承来扩展已有的类，创建新的类。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In TypeScript, we can use common object-oriented patterns. Of course, one of the most fundamental patterns in class-based programming is being able to extend existing classes to create new ones using inheritance.
</p></div><div role="item"><p>让我们来看一个例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Let&#39;s take a look at an example:
</p></div><pre><code class="lang-js">class Animal {
    name:string;
    constructor(theName: string) { this.name = theName; }
    move(meters: number = 0) {
        alert(this.name + &quot; moved &quot; + meters + &quot;m.&quot;);
    }
}

class Snake extends Animal {
    constructor(name: string) { super(name); }
    move(meters = 5) {
        alert(&quot;Slithering...&quot;);
        super.move(meters);
    }
}

class Horse extends Animal {
    constructor(name: string) { super(name); }
    move(meters = 45) {
        alert(&quot;Galloping...&quot;);
        super.move(meters);
    }
}

var sam = new Snake(&quot;Sammy the Python&quot;);
var tom: Animal = new Horse(&quot;Tommy the Palomino&quot;);

sam.move();
tom.move(34);
</code></pre>
<div role="item"><p>这个例子涵盖了不少其他语言中常见的，同时也属于TypeScript的继承特性。我们看到这里使用了&#39;extends&#39;关键字来创建一个子类。这里的&#39;Horse&#39;和&#39;Snake&#39;继承超类&#39;Animal&#39;并能访问超类的成员。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">This example covers quite a bit of the inheritance features in TypeScript that are common to other languages. Here we see using the &#39;extends&#39; keywords to create a subclass. You can see this where &#39;Horse&#39; and &#39;Snake&#39; subclass the base class &#39;Animal&#39; and gain access to its features.
</p></div><div role="item"><p>这个例子同时也展示了我们可以通过在子类上进行特定的定义以重写超类中的方法。这里的&#39;Snake&#39;和&#39;Horse&#39;都创建了一个&#39;move&#39;方法,来重写&#39;Animal&#39;中的&#39;move&#39;方法，从而给予每个类特定的功能。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The example also shows off being able to override methods in the base class with methods that are specialized for the subclass. Here both &#39;Snake&#39; and &#39;Horse&#39; create a &#39;move&#39; method that overrides the &#39;move&#39; from &#39;Animal&#39;, giving it functionality specific to each class.
</p></div><h2 class="section-title"><a name="Private/Public修饰语" class="anchor" href="#Private/Public修饰语"><span class="header-link"></span></a>Private/Public修饰语</h2><h3 class="section-title"><a name="默认为Public" class="anchor" href="#默认为Public"><span class="header-link"></span></a>默认为Public</h3><div role="item"><p>你可能已经注意到了，在前面的例子中，我们没有用关键词&#39;public&#39;来标识类成员的可见性。像在C#等语言中，每个对外部可见的成员都需要用&#39;public&#39;进行明确地标识。而在TypeScript中，每个成员都被默认为公有。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">You may have noticed in the above examples we haven&#39;t had to use the word &#39;public&#39; to make any of the members of the class visible. Languages like C# require that each member be explicitly labelled &#39;public&#39; to be visible. In TypeScript, each member is public by default. 
</p></div><div role="item"><p>你仍旧可以将一个成员标识为private，这样你就能够控制对类外部来说可见的部分。我们可以像下面这样来写前面的例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">You may still mark members a private, so you control what is publicly visible outside of your class. We could have written the &#39;Animal&#39; class from the previous section like so:
</p></div><pre><code class="lang-js">class Animal {
    private name:string;
    constructor(theName: string) { this.name = theName; }
    move(meters: number) {
        alert(this.name + &quot; moved &quot; + meters + &quot;m.&quot;);
    }
}
</code></pre>
<h3 class="section-title"><a name="理解private" class="anchor" href="#理解private"><span class="header-link"></span></a>理解private</h3><div role="item"><p>TypeScript使用结构化类型系统（structural type system）。当我们比较两种不同的数据类型时，我们会忽略它们是怎么来的。只要它们的每个成员都是一致的，我们就说这两种类型是一致的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">TypeScript is a structural type system. When we compare two different types, regardless of where they came from, if the types of each member are compatible, then we say the types themselves are compatible. 
</p></div><div role="item"><p>而当比较拥有私有成员的类型时，情况会稍有不同。当比较两种类型是否兼容时，如果其中一种类型拥有私有成员，那么只有当另一种类型也对应拥有具有相同定义的私有成员时，我们才说这两种类型是兼容的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When comparing types that have &#39;private&#39; members, we treat these differently. For two types to be considered compatible, if one of them has a private member, then the other must have a private member that originated in the same declaration. 
</p></div><div role="item"><p>为了更好地理解这是怎么回事，我们可以看看下面的例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Let&#39;s look at an example to better see how this plays out in practice:
</p></div><pre><code class="lang-js">class Animal {
    private name:string;
    constructor(theName: string) { this.name = theName; }
}

class Rhino extends Animal {
  constructor() { super(&quot;Rhino&quot;); }
}

class Employee {
    private name:string;
    constructor(theName: string) { this.name = theName; } 
}

var animal = new Animal(&quot;Goat&quot;);
var rhino = new Rhino();
var employee = new Employee(&quot;Bob&quot;);

animal = rhino;
animal = employee; //error: Animal and Employee are not compatible
</code></pre>
<div role="item"><p>在这个例子中，我们有一个&#39;Animal&#39;和&#39;Animal&#39;的子类——&#39;Rhino&#39;。同时我们也有一个看起来和&#39;Animal&#39;结构一样的&#39;Employee&#39;。我们生成了这些类的实例并尝试把它们互相赋值给对方，来看看会产生什么结果。因为&#39;Animal&#39;和&#39;Rhino&#39;的&#39;private name: string&#39;声明的来源相同，私有部分相同，所以我们说它们是兼容的。而&#39;Employee&#39;的则不同。当尝试将一个&#39;Employee&#39;的实例赋值给&#39;Animal&#39;类型的变量时，我们会得到这些类型不兼容的错误。尽管&#39;Employee&#39;同样有一个名为&#39;name&#39;的私有成员，但它与&#39;Animal&#39;中的&#39;name&#39;来源不同。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In this example, we have an &#39;Animal&#39; and a &#39;Rhino&#39;, with &#39;Rhino&#39; being a subclass of &#39;Animal&#39;. We also have a new class &#39;Employee&#39; that looks identical to &#39;Animal&#39; in terms of shape. We create some instances of these classes and then try to assign them to each other to see what will happen. Because &#39;Animal&#39; and &#39;Rhino&#39; share the private side of their shape from the same declaration of &#39;private name: string&#39; in &#39;Animal&#39;, they are compatible. However, this is not the case for &#39;Employee&#39;. When we try to assign from an &#39;Employee&#39; to &#39;Animal&#39; we get an error that these types are not compatible. Even though &#39;Employee&#39; also has a private member called &#39;name&#39;, it is not the same one as the one created in &#39;Animal&#39;. 
</p></div><h3 class="section-title"><a name="参数属性" class="anchor" href="#参数属性"><span class="header-link"></span></a>参数属性</h3><div role="item"><p>&#39;public&#39;和&#39;private&#39;关键字同样也允许我们通过创建参数属性，来便捷地创建并初始化类的成员的。这些属性允许我们只通过一个步骤就创建并初始化一个成员。下面是前面例子的另一个版本。注意这里我们没有用&#39;theName&#39;，而是直接在构造函数里声明了个&#39;private name: string&#39;的参数，就并创建和初始化了&#39;name&#39;成员。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The keywords &#39;public&#39; and &#39;private&#39; also give you a shorthand for creating and initializing members of your class, by creating parameter properties. The properties let you can create and initialize a member in one step. Here&#39;s a further revision of the previous example. Notice how we drop &#39;theName&#39; altogether and just use the shortened &#39;private name: string&#39; parameter on the constructor to create and initialize the &#39;name&#39; member.
</p></div><pre><code class="lang-js">class Animal {
    constructor(private name: string) { }
    move(meters: number) {
        alert(this.name + &quot; moved &quot; + meters + &quot;m.&quot;);
    }
}
</code></pre>
<div role="item"><p>这里使用&#39;private&#39;创建并初始化了一个私有成员。这对&#39;public&#39;来说也是相似的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Using &#39;private&#39; in this way creates and initializes a private member, and similarly for &#39;public&#39;. 
</p></div><h2 class="section-title"><a name="访问器（Accessors）" class="anchor" href="#访问器（Accessors）"><span class="header-link"></span></a>访问器（Accessors）</h2><div role="item"><p>TypeScript支持用getters/setters与对象中的成员进行交互。这为我们提供了一个控制对对象成员的访问的好方法。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">TypeScript supports getters/setters as a way of intercepting accesses to a member of an object. This gives you a way of having finer-grained control over how a member is accessed on each object.
</p></div><div role="item"><p>让我们用&#39;get&#39;和&#39;set&#39;来重写一个类。首先是一个没有getters和setters的例子。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Let&#39;s convert a simple class to use &#39;get&#39; and &#39;set&#39;. First, let&#39;s start with an example without getters and setters.
</p></div><pre><code class="lang-js">class Employee {
    fullName: string;
}

var employee = new Employee();
employee.fullName = &quot;Bob Smith&quot;;
if (employee.fullName) {
    alert(employee.fullName);
}
</code></pre>
<div role="item"><p>虽然允许直接设置fullName确实很方便，但如果我们能胡乱地设置它的值话，这种方式就可能会给我们来带麻烦。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">While allowing people to randomly set fullName directly is pretty handy, this might get us in trouble if we people can change names on a whim. 
</p></div><div role="item"><p>在下面这个版本的例子中，在允许用户修改雇员的信息之前，我们会检查并确保用户提供了密码。我们用一个&#39;set&#39;方法替代了直接访问&#39;fullName&#39;的方式，并对密码进行了检查。同时我们也对应添加了一个&#39;get&#39;方法来保证前面例子的代码在这里也能够继续运行。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In this version, we check to make sure the user has a secret passcode available before we allow them to modify the employee. We do this by replacing the direct access to fullName with a &#39;set&#39; that will check the passcode. We add a corresponding &#39;get&#39; to allow the previous example to continue to work seamlessly.
</p></div><pre><code class="lang-js">var passcode = &quot;secret passcode&quot;;

class Employee {
    private _fullName: string;

    get fullName(): string {
        return this._fullName;
    }

    set fullName(newName: string) {
        if (passcode &amp;&amp; passcode == &quot;secret passcode&quot;) {
            this._fullName = newName;
        }
        else {
            alert(&quot;Error: Unauthorized update of employee!&quot;);
        }
    }
}

var employee = new Employee();
employee.fullName = &quot;Bob Smith&quot;;
if (employee.fullName) {
    alert(employee.fullName);
}
</code></pre>
<div role="item"><p>为了证明我们的存取器确实在检查密码，我们可以尝试修改一下密码。结果我们得到了一个警告，提示我们没有获取和修改employee的权利。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To prove to ourselves that our accessor is now checking the passcode, we can modify the passcode and see that when it doesn&#39;t match we instead get the alert box warning us we don&#39;t have access to update the employee.
</p></div><div role="item"><p>注意：要使用访问器的话，我们需要设置编译器生成ECMAScript 5代码。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Note: Accessors require you to set the compiler to output ECMAScript 5.
</p></div><h2 class="section-title"><a name="静态属性" class="anchor" href="#静态属性"><span class="header-link"></span></a>静态属性</h2><div role="item"><p>到目前为止，我们都在谈论类的实例上的成员，它们只有在对象被实例化后才能从该对象获取。但我们也可以给一个类创建静态成员，这些静态成员在类上就是可见的，而不是在实例生成后才能获得。在这个例子中，由于&#39;origin&#39;是所有&#39;grids&#39;都具备的一个通用的值，所以我们用&#39;static&#39;来声明&#39;origin&#39;。每一个实例都可以通过在成员名之前加上类的名字来获得静态成员，这和&#39;this.&#39;前缀很相似。这里我们在获取静态成员时，在前面加上了&#39;Grid.&#39;。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Up to this point, we&#39;ve only talked about the instance members of the class, those that show up on the object when its instantiated. We can also create static members of a class, those that are visible on the class itself rather than on the instances. In this example, we use &#39;static&#39; on the origin, as it&#39;s a general value for all grids. Each instance accesses this value through prepending the name of the class. Similarly to prepending &#39;this.&#39; in front of instance accesses, here we prepend &#39;Grid.&#39; in front of static accesses.
</p></div><pre><code class="lang-js">class Grid {
    static origin = {x: 0, y: 0};
    calculateDistanceFromOrigin(point: {x: number; y: number;}) {
        var xDist = (point.x - Grid.origin.x);
        var yDist = (point.y - Grid.origin.y);
        return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
    }
    constructor (public scale: number) { }
}

var grid1 = new Grid(1.0);  // 1x scale
var grid2 = new Grid(5.0);  // 5x scale

alert(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
alert(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
</code></pre>
<h2 class="section-title"><a name="高级技巧" class="anchor" href="#高级技巧"><span class="header-link"></span></a>高级技巧</h2><h3 class="section-title"><a name="构造函数" class="anchor" href="#构造函数"><span class="header-link"></span></a>构造函数</h3><div role="item"><p>当你在TypeScript中声明一个类时，实际上你同时创建了多个定义。其中第一个创建的便是类对应的实例的类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When you declare a class in TypeScript, you are actually creating multiple declarations at the same time. The first is the type of the instance of the class.
</p></div><pre><code class="lang-js">class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return &quot;Hello, &quot; + this.greeting;
    }
}

var greeter: Greeter;
greeter = new Greeter(&quot;world&quot;);
alert(greeter.greet());
</code></pre>
<div role="item"><p>这里的&#39;var greeter: Greeter&#39;表示我们把Greeter当作Greeter实例的类型。这种做法都快成为习惯面向对象的程序员的天性了。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Here, when we say &#39;var greeter: Greeter&#39;, we&#39;re using Greeter as the type of instances of the class Greeter. This is almost second nature to programmers from other object-oriented languages. 
</p></div><div role="item"><p>我们也创建了一个我们称作构造函数的函数。当我们&#39;new&#39;一个实例时这个方法就会被调用。让我们看看前面例子的代码所编译成的JavaScript代码，来看看这到底是怎么回事。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">We&#39;re also creating another value that we call the constructor function. This is the function that is called when we &#39;new&#39; up instances of the class. To see what this looks like in practice, let&#39;s take a look at the JavaScript created by the above example:
</p></div><pre><code class="lang-js">var Greeter = (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return &quot;Hello, &quot; + this.greeting;
    };
    return Greeter;
})();

var greeter;
greeter = new Greeter(&quot;world&quot;);
alert(greeter.greet());
</code></pre>
<div role="item"><p>这里的&#39;var Greeter&#39;被赋值给了构造函数。当我们使用&#39;new&#39;并运行这个函数时，我们获得了这个类的一个实例。这个构造函数同样也包含了这个类所有的静态成员。我们可以认为每个类中都有属于实例的部分和静态部分。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Here, &#39;var Greeter&#39; is going to be assigned the constructor function. When we call &#39;new&#39; and run this function, we get an instance of the class. The constructor function also contains all of the static members of the class. Another way to think of each class is that there is an instance side and a static side.
</p></div><div role="item"><p>让我们稍微修改一下这个例子，看看会有什么不同：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Let&#39;s modify the example a bit to show this difference:
</p></div><pre><code class="lang-js">class Greeter {
    static standardGreeting = &quot;Hello, there&quot;;
    greeting: string;
    greet() {
        if (this.greeting) {
            return &quot;Hello, &quot; + this.greeting;
        }
        else {
            return Greeter.standardGreeting;
        }
    }
}

var greeter1: Greeter;
greeter1 = new Greeter();
alert(greeter1.greet());

var greeterMaker: typeof Greeter = Greeter;
greeterMaker.standardGreeting = &quot;Hey there!&quot;;
var greeter2:Greeter = new greeterMaker();
alert(greeter2.greet());
</code></pre>
<div role="item"><p>在这个例子中，&#39;greeter1&#39;运行得和之前差不多。我们生成了&#39;Greeter&#39;类的实例并使用了这个实例对象。这种用法我们之前已经见过了。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In this example, &#39;greeter1&#39; works similarly to before. We instantiate the &#39;Greeter&#39; class, and use this object. This we have seen before.
</p></div><div role="item"><p>接着，我们直接使用这个类。我们创建了一个名为&#39;greeterMaker&#39;的新变量。这个变量获得的是这个类本身，或者应该说是这个类的构造函数。这里我们用&#39;typeof Greeter&#39;的意义是&quot;给我Greeter类本身的类型&quot;而不是实例的类型。或者更准确地来讲应该是&quot;给我这个名为Greeter的标识的类型&quot;，即构造函数的类型。Greeter类型（的变量）会包含所有Greeter的静态成员，这些静态成员会存在于Greeter构造函数的里面。为了展示这一点，我们在&#39;greeterMaker&#39;上使用&#39;new&#39;来创建&#39;Greeter&#39;的新实例，并像之前那样使用他们。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Next, we then use the class directly. Here we create a new variable called &#39;greeterMaker&#39;. This variable will hold the class itself, or said another way its constructor function. Here we use &#39;typeof Greeter&#39;, that is &quot;give me the type of the Greeter class itself&quot; rather than the instance type. Or, more precisely, &quot;give me the type of the symbol called Greeter&quot;, which is the type of the constructor function. This type will contain all of the static members of Greeter along with the constructor that creates instances of the Greeter class. We show this by using &#39;new&#39; on &#39;greeterMaker&#39;, creating new instances of &#39;Greeter&#39; and invoking them as before.
</p></div><h3 class="section-title"><a name="把一个类当作接口来用" class="anchor" href="#把一个类当作接口来用"><span class="header-link"></span></a>把一个类当作接口来用</h3><div role="item"><p>就像我们前面说过的，一个类的声明会创造两个东西：一个是这个类的实例的类型，另一个是构造函数。因为类会创造类型，所以我们可以在使用接口的地方使用类。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">As we said in the previous section, a class declaration creates two things: a type representing instances of the class and a constructor function. Because classes create types, you can use them in the same places you would be able to use interfaces.
</p></div><pre><code class="lang-js">class Point {
    x: number;
    y: number;
}

interface Point3d extends Point {
    z: number;
}

var point3d: Point3d = {x: 1, y: 2, z: 3};
</code></pre>
<hr>
<h1 class="section-title"><a name="模块" class="anchor" href="#模块"><span class="header-link"></span></a>模块</h1><div role="item"><p>本部分将概述TypeScript中的各种用模块组织代码的方式。内容不仅会覆盖内部模块和外部模块，我们还将讨论每种模块应当在何时使用以及如何使用。同时我们也会对如何使用外部模块，以及在TypeScript中使用模块可能会产生的隐患等进阶话题进行讨论。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">This post outlines the various ways to organize your code using modules in TypeScript. We&#39;ll be covering internal and external modules and we&#39;ll discuss when each is appropriate and how to use them. We&#39;ll also go over some advanced topics of how to use external modules, and address some common pitfalls when using modules in TypeScript.
</p></div><h3 class="section-title"><a name="第一步" class="anchor" href="#第一步"><span class="header-link"></span></a>第一步</h3><div role="item"><p>我们首先从下面这段程序讲起，我们通篇都会用到它。我们写了一些非常简单的字符串验证方法，你平时可能也会用这些方法来检查网页用户在表单上的输入，或是用它们检查来自外部的数据的格式。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Let&#39;s start with the program we&#39;ll be using as our example throughout this page. We&#39;ve written a small set of simplistic string validators, like you might use when checking a user&#39;s input on a form in a webpage or checking the format of an externally-provided data file.
</p></div><p><strong>写在一个文件中的验证器</strong></p>
<pre><code class="lang-js">interface StringValidator {
    isAcceptable(s: string): boolean;
}

var lettersRegexp = /^[A-Za-z]+$/;
var numberRegexp = /^[0-9]+$/;

class LettersOnlyValidator implements StringValidator {
    isAcceptable(s: string) {
        return lettersRegexp.test(s);
    }
}

class ZipCodeValidator implements StringValidator {
    isAcceptable(s: string) {
        return s.length === 5 &amp;&amp; numberRegexp.test(s);
    }
}

// Some samples to try
var strings = [&#39;Hello&#39;, &#39;98052&#39;, &#39;101&#39;];
// Validators to use
var validators: { [s: string]: StringValidator; } = {};
validators[&#39;ZIP code&#39;] = new ZipCodeValidator();
validators[&#39;Letters only&#39;] = new LettersOnlyValidator();
// Show whether each string passed each validator
strings.forEach(s =&gt; {
    for (var name in validators) {
        console.log(&#39;&quot;&#39; + s + &#39;&quot; &#39; + (validators[name].isAcceptable(s) ? &#39; matches &#39; : &#39; does not match &#39;) + name);
    }
});
</code></pre>
<h3 class="section-title"><a name="加入模块" class="anchor" href="#加入模块"><span class="header-link"></span></a>加入模块</h3><div role="item"><p>当我们添加了更多的验证方法以后，我们会想要以某种方式来组织我们的代码，好让我们能够追踪我们创建的这类类型，同时也不用担心它们与其他对象发生命名冲突。我们应该把所创建的对象包裹进一个模块中，而不在全局环境给它们取一堆不同的名字。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">As we add more validators, we&#39;re going to want to have some kind of organization scheme so that we can keep track of our types and not worry about name collisions with other objects. Instead of putting lots of different names into the global namespace, let&#39;s wrap up our objects into a module.
</p></div><div role="item"><p>在这个例子中，我们已经把所有和验证相关的类型都放进了一个名为&#39;Validation&#39;的模块中。为了使这里的接口和类对模块外部可见，我们在开头用export关键词修饰它们。相反的，变量&#39;lettersRegexp&#39;和&#39;numberRegexp&#39;都是验证中的细节部分，我们将保持它们的非输出的状态，使其在外部不可见。由下面例子后面的测试代码我们可以知道，当在模块外面使用时，我们需要指定验证类型，如：Validation.LettersOnlyValidator。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In this example, we&#39;ve moved all the Validator-related types into a module called Validation. Because we want the interfaces and classes here to be visible outside the module, we preface them with export. Conversely, the variables lettersRegexp and numberRegexp are implementation details, so they are left unexported and will not be visible to code outside the module. In the test code at the bottom of the file, we now need to qualify the names of the types when used outside the module, e.g. Validation.LettersOnlyValidator.
</p></div><p><strong>模块化后的验证器</strong></p>
<pre><code class="lang-js">module Validation {
    export interface StringValidator {
        isAcceptable(s: string): boolean;
    }

    var lettersRegexp = /^[A-Za-z]+$/;
    var numberRegexp = /^[0-9]+$/;

    export class LettersOnlyValidator implements StringValidator {
        isAcceptable(s: string) {
            return lettersRegexp.test(s);
        }
    }

    export class ZipCodeValidator implements StringValidator {
        isAcceptable(s: string) {
            return s.length === 5 &amp;&amp; numberRegexp.test(s);
        }
    }
}

// Some samples to try
var strings = [&#39;Hello&#39;, &#39;98052&#39;, &#39;101&#39;];
// Validators to use
var validators: { [s: string]: Validation.StringValidator; } = {};
validators[&#39;ZIP code&#39;] = new Validation.ZipCodeValidator();
validators[&#39;Letters only&#39;] = new Validation.LettersOnlyValidator();
// Show whether each string passed each validator
strings.forEach(s =&gt; {
    for (var name in validators) {
        console.log(&#39;&quot;&#39; + s + &#39;&quot; &#39; + (validators[name].isAcceptable(s) ? &#39; matches &#39; : &#39; does not match &#39;) + name);
    }
});
</code></pre>
<h2 class="section-title"><a name="分割成多个文件" class="anchor" href="#分割成多个文件"><span class="header-link"></span></a>分割成多个文件</h2><div role="item"><p>随着应用规模的逐渐扩大，我们需要将代码分割成多个文件，以使其更易维护。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">As our application grows, we&#39;ll want to split the code across multiple files to make it easier to maintain.
</p></div><div role="item"><p>在这里，我们将验证模块分成了多个文件。尽管这些文件是分散开的，但它们都像是定义在同一个地方一样，作用于同一个模块中。因为这些文件之间互有依赖关系，所以我们添加了引用标签来告诉编译器这些文件之间的关系。测试代码并没有变化。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Here, we&#39;ve split our Validation module across many files. Even though the files are separate, they can each contribute to the same module and can be consumed as if they were all defined in one place. Because there are dependencies between files, we&#39;ve added reference tags to tell the compiler about the relationships between the files. Our test code is otherwise unchanged.
</p></div><h3 class="section-title"><a name="多文件的内部模块" class="anchor" href="#多文件的内部模块"><span class="header-link"></span></a>多文件的内部模块</h3><p><strong>Validation.ts</strong></p>
<pre><code class="lang-js">module Validation {
    export interface StringValidator {
        isAcceptable(s: string): boolean;
    }
}
</code></pre>
<p><strong>LettersOnlyValidator.ts</strong></p>
<pre><code class="lang-js">/// &lt;reference path=&quot;Validation.ts&quot; /&gt;
module Validation {
    var lettersRegexp = /^[A-Za-z]+$/;
    export class LettersOnlyValidator implements StringValidator {
        isAcceptable(s: string) {
            return lettersRegexp.test(s);
        }
    }
}
</code></pre>
<p><strong>ZipCodeValidator.ts</strong></p>
<pre><code class="lang-js">/// &lt;reference path=&quot;Validation.ts&quot; /&gt;
module Validation {
    var numberRegexp = /^[0-9]+$/;
    export class ZipCodeValidator implements StringValidator {
        isAcceptable(s: string) {
            return s.length === 5 &amp;&amp; numberRegexp.test(s);
        }
    }
}
</code></pre>
<p><strong>Test.ts</strong></p>
<pre><code class="lang-js">/// &lt;reference path=&quot;Validation.ts&quot; /&gt;
/// &lt;reference path=&quot;LettersOnlyValidator.ts&quot; /&gt;
/// &lt;reference path=&quot;ZipCodeValidator.ts&quot; /&gt;

// Some samples to try
var strings = [&#39;Hello&#39;, &#39;98052&#39;, &#39;101&#39;];
// Validators to use
var validators: { [s: string]: Validation.StringValidator; } = {};
validators[&#39;ZIP code&#39;] = new Validation.ZipCodeValidator();
validators[&#39;Letters only&#39;] = new Validation.LettersOnlyValidator();
// Show whether each string passed each validator
strings.forEach(s =&gt; {
    for (var name in validators) {
        console.log(&#39;&quot;&#39; + s + &#39;&quot; &#39; + (validators[name].isAcceptable(s) ? &#39; matches &#39; : &#39; does not match &#39;) + name);
    }
});
</code></pre>
<div role="item"><p>当项目涉及到多个文件时，我们就必须保证所有编译后的代码都能被加载进来。我们有两种方法来实现这一点。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Once there are multiple files involved, we&#39;ll need to make sure all of the compiled code gets loaded. There are two ways of doing this.
</p></div><div role="item"><p>第一种方法是通过--out flag来将输入的所有文件内容连接起来，并将结果输出到单个JavaScript文件中：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">First, we can use concatenated output using the --out flag to compile all of the input files into a single JavaScript output file:
</p></div><pre><code>tsc --out sample.js Test.ts
</code></pre><div role="item"><p>编译器将会根据在文件中出现的引用标签自动地排序输出文件的内容。但你也可以手动指定每个文件的输出顺序：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The compiler will automatically order the output file based on the reference tags present in the files. You can also specify each file individually:
</p></div><pre><code>tsc --out sample.js Validation.ts LettersOnlyValidator.ts ZipCodeValidator.ts Test.ts
</code></pre><div role="item"><p>另外，我们也可以使用分别输出每个文件的编译方式（这是默认选项）。生成多个JS文件以后，我们需要在网页上用&lt;script&gt;标签按恰当的顺序加载每个文件，像是下面的例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Alternatively, we can use per-file compilation (the default) to emit one JavaScript file for each input file. If multiple JS files get produced, we&#39;ll need to use &lt;script&gt; tags on our webpage to load each emitted file in the appropriate order, for example:
</p></div><p><strong>MyTestPage.html (部分代码)</strong></p>
<pre><code class="lang-html">    &lt;script src=&quot;Validation.js&quot; type=&quot;text/javascript&quot; /&gt;
    &lt;script src=&quot;LettersOnlyValidator.js&quot; type=&quot;text/javascript&quot; /&gt;
    &lt;script src=&quot;ZipCodeValidator.js&quot; type=&quot;text/javascript&quot; /&gt;
    &lt;script src=&quot;Test.js&quot; type=&quot;text/javascript&quot; /&gt;
</code></pre>
<h2 class="section-title"><a name="使用外部代码" class="anchor" href="#使用外部代码"><span class="header-link"></span></a>使用外部代码</h2><div role="item"><p>TypeScript同样也有外部模块的概念。在用到node.js或require.js时我们需要使用外部模块。对于没有用到node.js或require.js的应用则不需要使用外部模块，因为前面讲到的内部模块就能够很好地组织起这类应用的代码。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">TypeScript also has the concept of an external module. External modules are used in two cases: node.js and require.js. Applications not using node.js or require.js do not need to use external modules and can best be organized using the internal module concept outlined above.
</p></div><div role="item"><p>在外部模块中，文件之间的关系是通过文件级别的输入和输出来指定的。在TypeSciprt中，任何包含顶级import和export关键字的文件都被认为是外部模块。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In external modules, relationships between files are specified in terms of imports and exports at the file level. In TypeScript, any file containing a top-level import or export is considered an external module.
</p></div><div role="item"><p>在下面的例子中，我们将前面的例子转换成了使用外部模块的形式。注意这里我们不再使用module关键字，文件本身就构成了一个模块。我们通过它们的文件名来识别它们。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Below, we have converted the previous example to use external modules. Notice that we no longer use the module keyword – the files themselves constitute a module and are identified by their filenames.
</p></div><div role="item"><p>这里我们用import声明替代了引用标签，import指定了模块间的依赖关系。import声明由两部分构成：require关键字用来指定当前文件所依赖的模块的路径，import后面指定的输入的模块在这个文件中的名称。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The reference tags have been replaced with import statements that specify the dependencies between modules. The import statement has two parts: the name that the module will be known by in this file, and the require keyword that specifies the path to the required module:
</p></div><pre><code class="lang-js">import someMod = require(&#39;someModule&#39;);
</code></pre>
<div role="item"><p>与我们用export定义一个内部模块的公共部分相似，这里我们在顶级声明上用export关键字来指定哪些对象对外部是可见的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">We specify which objects are visible outside the module by using the export keyword on a top-level declaration, similarly to how export defined the public surface area of an internal module.
</p></div><div role="item"><p>编译时，我们需要在命令行上指定该模块的编译类型。对于node.js来说，要用 --module commonjs；对于require.js来说，要用--module amd。来看下面的例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To compile, we must specify a module target on the command line. For node.js, use --module commonjs; for require.js, use --module amd. For example:
</p></div><pre><code>tsc --module commonjs Test.ts
</code></pre><div role="item"><p>编译以后，每个外部模块都会变成一个分离的.js文件。类似引用标签，编译器会根据import声明来编译相互依赖的文件。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When compiled, each external module will become a separate .js file. Similar to reference tags, the compiler will follow import statements to compile dependent files.
</p></div><p><strong>Validation.ts</strong></p>
<pre><code class="lang-js">export interface StringValidator {
    isAcceptable(s: string): boolean;
}
</code></pre>
<p><strong>LettersOnlyValidator.ts</strong></p>
<pre><code class="lang-js">import validation = require(&#39;./Validation&#39;);
var lettersRegexp = /^[A-Za-z]+$/;
export class LettersOnlyValidator implements validation.StringValidator {
    isAcceptable(s: string) {
        return lettersRegexp.test(s);
    }
}
</code></pre>
<p><strong>ZipCodeValidator.ts</strong></p>
<pre><code class="lang-js">import validation = require(&#39;./Validation&#39;);
var numberRegexp = /^[0-9]+$/;
export class ZipCodeValidator implements validation.StringValidator {
    isAcceptable(s: string) {
        return s.length === 5 &amp;&amp; numberRegexp.test(s);
    }
}
</code></pre>
<p><strong>Test.ts</strong></p>
<pre><code class="lang-js">import validation = require(&#39;./Validation&#39;);
import zip = require(&#39;./ZipCodeValidator&#39;);
import letters = require(&#39;./LettersOnlyValidator&#39;);

// Some samples to try
var strings = [&#39;Hello&#39;, &#39;98052&#39;, &#39;101&#39;];
// Validators to use
var validators: { [s: string]: validation.StringValidator; } = {};
validators[&#39;ZIP code&#39;] = new zip.ZipCodeValidator();
validators[&#39;Letters only&#39;] = new letters.LettersOnlyValidator();
// Show whether each string passed each validator
strings.forEach(s =&gt; {
    for (var name in validators) {
        console.log(&#39;&quot;&#39; + s + &#39;&quot; &#39; + (validators[name].isAcceptable(s) ? &#39; matches &#39; : &#39; does not match &#39;) + name);
    }
});
</code></pre>
<h3 class="section-title"><a name="外部模块代码生成" class="anchor" href="#外部模块代码生成"><span class="header-link"></span></a>外部模块代码生成</h3><div role="item"><p>编译器会根据编译时指定的类型，为node.js (commonjs)和require.js (AMD)的模块加载系统生成合适的代码。你可以查看每个模块加载器的文档来了解生成代码中的define和require到底做了什么。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Depending on the module target specified during compilation, the compiler will generate appropriate code for either node.js (commonjs) or require.js (AMD) module-loading systems. For more information on what the define and require calls in the generated code do, consult the documentation for each module loader.
</p></div><div role="item"><p>下面这个例子展示了import和export语句是如何转换成模块加载代码的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">This simple example shows how the names used during importing and exporting get translated into the module loading code.
</p></div><p><strong>SimpleModule.ts</strong></p>
<pre><code class="lang-js">import m = require(&#39;mod&#39;);
export var t = m.something + 1;
</code></pre>
<p><strong>AMD / RequireJS SimpleModule.js:</strong></p>
<pre><code class="lang-js">define([&quot;require&quot;, &quot;exports&quot;, &#39;mod&#39;], function(require, exports, m) {
    exports.t = m.something + 1;
});
</code></pre>
<p><strong>CommonJS / Node SimpleModule.js:</strong></p>
<pre><code class="lang-js">var m = require(&#39;mod&#39;);
exports.t = m.something + 1;
</code></pre>
<h2 class="section-title"><a name="Export =" class="anchor" href="#Export ="><span class="header-link"></span></a>Export =</h2><div role="item"><p>在前面的例子中，我们使用validator时，每个模块都只输出一个值。在这种情况下，虽然我们用一个标识符就可以了，但我们仍需要一个限定名。这样的做法显得很繁重。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In the previous example, when we consumed each validator, each module only exported one value. In cases like this, it&#39;s cumbersome to work with these symbols through their qualified name when a single identifier would do just as well.
</p></div><div role="item"><p>而&quot;export =&quot;句法可以指定模块要输出的单一对象。这个对象可以是类，接口，模块，函数或枚举类型。每当这个模块被输入时，其输出的东西就可以被直接使用，而不需要再在模块上加上任何名称。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The export = syntax specifies a single object that is exported from the module. This can be a class, interface, module, function, or enum. When imported, the exported symbol is consumed directly and is not qualified by any name.
</p></div><div role="item"><p>在下面的例子中，我们用&quot;export =&quot;句法简化了前面Validator的实现，每个模块只会输出一个对象。这种做法简化了使用模块的代码——我们可以直接引用&#39;zipValidator&#39;而不需要用&#39;zip.ZipCodeValidator&#39;。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Below, we&#39;ve simplified the Validator implementations to only export a single object from each module using the export = syntax. This simplifies the consumption code – instead of referring to &#39;zip.ZipCodeValidator&#39;, we can simply refer to &#39;zipValidator&#39;.
</p></div><p><strong>Validation.ts</strong></p>
<pre><code class="lang-js">export interface StringValidator {
    isAcceptable(s: string): boolean;
}
</code></pre>
<p><strong>LettersOnlyValidator.ts</strong></p>
<pre><code class="lang-js">import validation = require(&#39;./Validation&#39;);
var lettersRegexp = /^[A-Za-z]+$/;
class LettersOnlyValidator implements validation.StringValidator {
    isAcceptable(s: string) {
        return lettersRegexp.test(s);
    }
}
export = LettersOnlyValidator;
</code></pre>
<p><strong>ZipCodeValidator.ts</strong></p>
<pre><code class="lang-js">import validation = require(&#39;./Validation&#39;);
var numberRegexp = /^[0-9]+$/;
class ZipCodeValidator implements validation.StringValidator {
    isAcceptable(s: string) {
        return s.length === 5 &amp;&amp; numberRegexp.test(s);
    }
}
export = ZipCodeValidator;
</code></pre>
<p><strong>Test.ts</strong></p>
<pre><code class="lang-js">import validation = require(&#39;./Validation&#39;);
import zipValidator = require(&#39;./ZipCodeValidator&#39;);
import lettersValidator = require(&#39;./LettersOnlyValidator&#39;);

// Some samples to try
var strings = [&#39;Hello&#39;, &#39;98052&#39;, &#39;101&#39;];
// Validators to use
var validators: { [s: string]: validation.StringValidator; } = {};
validators[&#39;ZIP code&#39;] = new zipValidator();
validators[&#39;Letters only&#39;] = new lettersValidator();
// Show whether each string passed each validator
strings.forEach(s =&gt; {
    for (var name in validators) {
        console.log(&#39;&quot;&#39; + s + &#39;&quot; &#39; + (validators[name].isAcceptable(s) ? &#39; matches &#39; : &#39; does not match &#39;) + name);
    }
});
</code></pre>
<h2 class="section-title"><a name="别名（Alias）" class="anchor" href="#别名（Alias）"><span class="header-link"></span></a>别名（Alias）</h2><div role="item"><p>另一种简化我们工作的做法是用&quot;import q = x.y.z&quot;来为常用对象创建短一些的名称。&quot;import q = x.y.z&quot;和用于加载外部模块的&quot;import x = require(&#39;name&#39;)&quot;是不一样的，它只会为指定的符号创建一个别名。我们可以将这类import（通常只是用作别名）用于任何类型标识符上，包括输入的外部模块所创建的对象。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Another way that you can simplify working with either kind of module is to use import q = x.y.z to create shorter names for commonly-used objects. Not to be confused with the import x = require(&#39;name&#39;) syntax used to load external modules, this syntax simply creates an alias for the specified symbol. You can use these sorts of imports (commonly referred to as aliases) for any kind of identifier, including objects created from external module imports.
</p></div><p><strong>Basic Aliasing</strong></p>
<pre><code class="lang-js">module Shapes {
    export module Polygons {
        export class Triangle { }
        export class Square { }
    }
}

import polygons = Shapes.Polygons;
var sq = new polygons.Square(); // Same as &#39;new Shapes.Polygons.Square()&#39;
</code></pre>
<div role="item"><p>注意这里我们没有使用require关键字，而是import的右侧赋值为我们导入对象的限定名。它的用法和var相似，但它同时也对导入对象的类型以及命名空间起作用。更重要的是，import的值是独立于原对象的一个引用，所以对别名变量的修改不会作用在原变量上。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Notice that we don&#39;t use the require keyword; instead we assign directly from the qualified name of the symbol we&#39;re importing. This is similar to using var, but also works on the type and namespace meanings of the imported symbol. Importantly, for values, import is a distinct reference from the original symbol, so changes to an aliased var will not be reflected in the original variable.
</p></div><h2 class="section-title"><a name="可选模块加载和其它一些特殊的加载情景" class="anchor" href="#可选模块加载和其它一些特殊的加载情景"><span class="header-link"></span></a>可选模块加载和其它一些特殊的加载情景</h2><div role="item"><p>在某些场景下，你可能需要在某些条件成立的情况下才加载一个模块。在TypeScript中，我们可以用后面展示的一些使用模式，来在保障数据类型安全的前提下触发模块加载器，以满足这种需求及其他特殊的模块加载场景。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In some cases, you may want to only load a module under some conditions. In TypeScript, we can use the pattern shown below to implement this and other advanced loading scenarios to directly invoke the module loaders without losing type safety.
</p></div><div role="item"><p>编译器会检测在生成的JavaScript中，一个模块到底有没有被使用。对于那些只会被用在类型系统上的模块来说，我们不需要调用require。这种挑选出被引用但却未被使用的模块的做法对性能大有脾益，同时也使加载可选模块成为了可能。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The compiler detects whether each module is used in the emitted JavaScript. For modules that are only used as part of the type system, no require calls are emitted. This culling of unused references is a good performance optimization, and also allows for optional loading of those modules.
</p></div><div role="item"><p>这一模式的核心思想在于我们可以通过import id = require(&#39;...&#39;)获取外部模块暴露出来的类型。就像下面的if语句块那样，模块加载器会被（require）动态触发，
使得我们可以筛选（reference-culling）优化，从而使模块可以按需加载。让这种模式起作用的关键在于保证我们通过import定义标识符只会发生在类型上（即编译时不会生成JavaScript代码）。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The core idea of the pattern is that the import id = require(&#39;...&#39;) statement gives us access to the types exposed by the external module. The module loader is invoked (through require) dynamically, as shown in the if blocks below. This leverages the reference-culling optimization so that the module is only loaded when needed. For this pattern to work, it&#39;s important that the symbol defined via import is only used in type positions (i.e. never in a position that would be emitted into the JavaScript).
</p></div><div role="item"><p>我们可以用typeof关键字来保证类型的安全。用在类型位置上的typeof关键字会生成值所对应的类型，在这个例子中所对应的是外部模块的类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To maintain type safety, we can use the typeof keyword. The typeof keyword, when used in a type position, produces the type of a value, in this case the type of the external module.
</p></div><p><strong>node.js中的动态模块加载</strong></p>
<pre><code class="lang-js">declare var require;
import Zip = require(&#39;./ZipCodeValidator&#39;);
if (needZipValidation) {
    var x: typeof Zip = require(&#39;./ZipCodeValidator&#39;);
    if (x.isAcceptable(&#39;.....&#39;)) { /* ... */ }
}
</code></pre>
<p><strong>require.js中的动态模块加载</strong></p>
<pre><code class="lang-js">declare var require;
import Zip = require(&#39;./ZipCodeValidator&#39;);
if (needZipValidation) {
    require([&#39;./ZipCodeValidator&#39;], (x: typeof Zip) =&gt; {
        if (x.isAcceptable(&#39;...&#39;)) { /* ... */ }
    });
}
</code></pre>
<h2 class="section-title"><a name="使用其他的JavaScript代码库" class="anchor" href="#使用其他的JavaScript代码库"><span class="header-link"></span></a>使用其他的JavaScript代码库</h2><div role="item"><p>我们需要声明非TypeScript代码库所暴露出来的API，才能描述代码库中的数据类型和结构。用模块的形式来表示这些库是很合适的，因为大多数JavaScript的代码库都只会暴露出一些顶层的对象。我们的声明并没有实现环境，通常这些定义都写在在.d.ts的文件中。如果你对C/C++很熟悉的话，你可以把它们当作是.h文件或是&quot;extern&quot; 。接下来让我们来看一些内部模块和外部模块的例子。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To describe the shape of libraries not written in TypeScript, we need to declare the API that the library exposes. Because most JavaScript libraries expose only a few top-level objects, modules are a good way to represent them. We call declarations that don&#39;t define an implementation &quot;ambient&quot;. Typically these are defined in .d.ts files. If you&#39;re familiar with C/C++, you can think of these as .h files or &#39;extern&#39;. Let&#39;s look at a few examples with both internal and external examples.
</p></div><h3 class="section-title"><a name="包裹成内部模块" class="anchor" href="#包裹成内部模块"><span class="header-link"></span></a>包裹成内部模块</h3><div role="item"><p>代码库D3把它的功能都定义在了一个名为&#39;D3&#39;的全局对象中。由于这个库是通过script标签加载的（而不是通过模块加载器），我们可以使用内部模块来定义它的结构。我们用一个ambient内部模块声明来让TypeScript的编译器可以了解它的结构。举个例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The popular library D3 defines its functionality in a global object called &#39;D3&#39;. Because this library is loaded through a script tag (instead of a module loader), its declaration uses internal modules to define its shape. For the TypeScript compiler to see this shape, we use an ambient internal module declaration. For example:
</p></div><p><strong>D3.d.ts (简要代码)</strong></p>
<pre><code class="lang-js">declare module D3 {
    export interface Selectors {
        select: {
            (selector: string): Selection;
            (element: EventTarget): Selection;
        };
    }

    export interface Event {
        x: number;
        y: number;
    }

    export interface Base extends Selectors {
        event: Event;
    }
}

declare var d3: D3.Base;
</code></pre>
<h3 class="section-title"><a name="包裹成外部模块" class="anchor" href="#包裹成外部模块"><span class="header-link"></span></a>包裹成外部模块</h3><div role="item"><p>node.js中的大多数的任务是通过加载多个模块来完成的。虽然我们可以在每个模块对应的.d.ts文件中用顶层的输出声明来定义这个模块，但把它们写成一个大的.d.ts文件会更加方便。我们会使用模块的引用名称来实现这一点，这个名称可以在后面的import中使用。举个例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In node.js, most tasks are accomplished by loading one or more modules. We could define each module in its own .d.ts file with top-level export declarations, but it&#39;s more convenient to write them as one larger .d.ts file. To do so, we use the quoted name of the module, which will be available to a later import. For example:
</p></div><p><strong>node.d.ts (简要代码)</strong></p>
<pre><code class="lang-js">declare module &quot;url&quot; {
    export interface Url {
        protocol?: string;
        hostname?: string;
        pathname?: string;
    }

    export function parse(urlStr: string, parseQueryString?, slashesDenoteHost?): Url;
}

declare module &quot;path&quot; {
    export function normalize(p: string): string;
    export function join(...paths: any[]): string;
    export var sep: string;
}
</code></pre>
<div role="item"><p>现在我们可以用&quot;/// <reference>&quot;来引用node.d.ts，并且我们可以用类似import url = require(&#39;url&#39;)的语句来加载相应模块。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Now we can /// <reference> node.d.ts and then load the modules using e.g. import url = require(&#39;url&#39;);.
</p></div><pre><code class="lang-js">///&lt;reference path=&quot;node.d.ts&quot;/&gt;
import url = require(&quot;url&quot;);
var myUrl = url.parse(&quot;http://www.typescriptlang.org&quot;);
</code></pre>
<h2 class="section-title"><a name="模块使用中的一些问题" class="anchor" href="#模块使用中的一些问题"><span class="header-link"></span></a>模块使用中的一些问题</h2><div role="item"><p>我们将在这一部分讲述使用内部模块和外部模块时会碰到的一些常见的陷阱，以及如何避免它们。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In this section we&#39;ll describe various common pitfalls in using internal and external modules, and how to avoid them.
</p></div><h3 class="section-title"><a name="/// <reference> to an external module" class="anchor" href="#/// <reference> to an external module"><span class="header-link"></span></a>/// <reference> to an external module</h3><div role="item"><p>一种常见的错误是用&quot;/// <reference>&quot;句法来引用一个外部模块文件（应该用import）。为了理解它们之间的差异，我们首先需要了解编译器定位外部模块信息的三种方式。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">A common mistake is to try to use the /// <reference> syntax to refer to an external module file, rather than using import. To understand the distinction, we first need to understand the three ways that the compiler can locate the type information for an external module.
</p></div><div role="item"><p>第一种方式是通过&quot;import x = require(...);&quot;声明查找对应的.ts文件。这个文件应该是带有顶层import或export声明的实现文件。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The first is by finding a .ts file named by an import x = require(...); declaration. That file should be an implementation file with top-level import or export declarations.
</p></div><div role="item"><p>第二种方式是查找一个.d.ts文件。这种做法与第一种做法相似，但这个文件是个声明文件（同样有顶层的import或export声明），而并没有具体的实现的代码。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The second is by finding a .d.ts file, similar to above, except that instead of being an implementation file, it&#39;s a declaration file (also with top-level import or export declarations).
</p></div><div role="item"><p>最后一种方式是利用&quot;ambient外部模块声明&quot;。对于这种方式，我们需要根据代码库来&#39;声明&#39;一个模块。
<strong>myModules.d.ts</strong><span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The final way is by seeing an &quot;ambient external module declaration&quot;, where we &#39;declare&#39; a module with a matching quoted name.
</p></div><pre><code class="lang-js">// In a .d.ts file or .ts file that is not an external module:
declare module &quot;SomeModule&quot; {
    export function fn(): string;
}
</code></pre>
<p><strong>myOtherModule.ts</strong></p>
<pre><code class="lang-js">/// &lt;reference path=&quot;myModules.d.ts&quot; /&gt;
import m = require(&quot;SomeModule&quot;);
</code></pre>
<div role="item"><p>这里的引用标签允许我们定位包含ambient外部模块的声明的声明文件。这同时也是不少TypeScript样例中的node.d.ts文件的用法。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The reference tag here allows us to locate the declaration file that contains the declaration for the ambient external module. This is how the node.d.ts file that several of the TypeScript samples use is consumed, for example.
</p></div><h3 class="section-title"><a name="冗余命名空间" class="anchor" href="#冗余命名空间"><span class="header-link"></span></a>冗余命名空间</h3><div role="item"><p>如果你想把一个程序从内部模块转换成外部模块，你很有可能会把文件写成这个样子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">If you&#39;re converting a program from internal modules to external modules, it can be easy to end up with a file that looks like this:
</p></div><p><strong>shapes.ts</strong></p>
<pre><code class="lang-js">export module Shapes {
    export class Triangle { /* ... */ }
    export class Square { /* ... */ }
}
</code></pre>
<div role="item"><p>这个例子用顶层模块Shapes无缘无故地包裹起了Triangle和Square。这么做会让该模块的使用者感到很费解和麻烦：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The top-level module here Shapes wraps up Triangle and Square for no reason. This is confusing and annoying for consumers of your module:
</p></div><p><strong>shapeConsumer.ts</strong></p>
<pre><code class="lang-js">import shapes = require(&#39;./shapes&#39;);
var t = new shapes.Shapes.Triangle(); // shapes.Shapes?
</code></pre>
<div role="item"><p>TypeScript中的外部模块有一个重要的特性，即两个不同的外部模块永远都不会把名称附着到同一个作用域上。因为外部模块的用户可以决定使用这个模块时的名称。所以你没有必要事先把要暴露出来的标识用一个命名空间包裹起来。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">A key feature of external modules in TypeScript is that two different external modules will never contribute names to the same scope. Because the consumer of an external module decides what name to assign it, there&#39;s no need to proactively wrap up the exported symbols in a namespace.<br></p></div><div role="item"><p>这里重申一下为什么我们不应该把外部模块放在命名空间里。命名空间是为了提供一个有逻辑意义的分组结构，并防止命名冲突。因为外部模块文件本身就已经是逻辑分组，并且它的顶层名称是由引入（import）它的代码所定义的，所以我们没有必要用额外的模块层来包裹这些输出对象。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To reiterate why you shouldn&#39;t try to namespace your external module contents, the general idea of namespacing is to provide logical grouping of constructs and to prevent name collisions. Because the external module file itself is already a logical grouping, and its top-level name is defined by the code that imports it, it&#39;s unnecessary to use an additional module layer for exported objects.
</p></div><div role="item"><p>修改后的例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Revised Example:
</p></div><p><strong>shapes.ts</strong></p>
<pre><code class="lang-js">export class Triangle { /* ... */ }
export class Square { /* ... */ }
</code></pre>
<p><strong>shapeConsumer.ts</strong></p>
<pre><code class="lang-js">import shapes = require(&#39;./shapes&#39;);
var t = new shapes.Triangle();
</code></pre>
<h3 class="section-title"><a name="外部模块的一些副作用" class="anchor" href="#外部模块的一些副作用"><span class="header-link"></span></a>外部模块的一些副作用</h3><div role="item"><p>就像每个JS文件和每个模块之间有一一对应的关系一样，TypeScript的外部模块的源码文件和它们生成的JS文件之间也有一一对应的关系。这种做法会产生一个副作用，即我们不可能用--out编译器开关把多个外部文件源码编译连接进同一个JavaScript文件中去。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Just as there is a one-to-one correspondence between JS files and modules, TypeScript has a one-to-one correspondence between external module source files and their emitted JS files. One effect of this is that it&#39;s not possible to use the --out compiler switch to concatenate multiple external module source files into a single JavaScript file.
</p></div><hr>
<h1 class="section-title"><a name="函数" class="anchor" href="#函数"><span class="header-link"></span></a>函数</h1><div role="item"><p>函数是构建JavaScript应用的基础。通过函数，我们可以把我们的业务逻辑抽象成多层，可以模仿类的实现，可以隐藏信息，可以构建模块。虽然TypeScript中已经有了类和模块，但在描述事物的执行过程时，函数仍旧起着关键的作用。TypeScript给标准的JavaScript函数添加了新的特性以方便我们更好地使用。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Functions are the fundamental building block of any applications in JavaScript. They&#39;re how you build up layers of abstraction, mimicking classes, information hiding, and modules. In TypeScript, while there are classes and modules, function still play the key role in describing how to &#39;do&#39; things. TypeScript also adds some new capabilities to the standard JavaScript functions to make them easier to work with.
</p></div><h2 class="section-title"><a name="函数" class="anchor" href="#函数"><span class="header-link"></span></a>函数</h2><div role="item"><p>首先，TypeScript和JavaScript一样，既可以创建有名称的函数也可以创建匿名函数。这允许我们在实现应用时选择最合适的方式。你既可以在API中生成一堆函数，也可以先构建个一次性的函数，之后再把它替换成另一个函数。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To begin, just as in JavaScript, TypeScript functions can be created both as a named function or as an anonymous function. This allows you to choose the most appropriate approach for your application, whether you&#39;re building a list of functions in an API or a one-off function to hand off to another function.
</p></div><div role="item"><p>让我们看看JavaScript中这两种应用方式的例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To quickly recap what these two approaches look like in JavaScript:
</p></div><pre><code class="lang-js">//Named function
function add(x, y) {
    return x+y;
}

//Anonymous function
var myAdd = function(x, y) { return x+y; };
</code></pre>
<div role="item"><p>和在JavaScript中一样，函数可以获得函数体外的变量。当它们获得了函数体外的变量时，我们说函数&#39;捕获&#39;了这些变量。虽然这一机制的工作方式以及它的副作用等内容可能已经超出了本文的叙述范围，但清楚地认识这一机制对我们使用JavaScript和TypeScript来说是不可或缺的一步。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Just as in JavaScript, functions can return to variables outside of the function body. When they do so, they&#39;re said to &#39;capture&#39; these variables. While understanding how this works, and the trade-offs when using this technique, are outside of the scope of this article, having a firm understanding how this mechanic is an important piece of working with JavaScript and TypeScript. 
</p></div><pre><code class="lang-js">var z = 100;

function addToZ(x, y) {
    return x+y+z;
}
</code></pre>
<h2 class="section-title"><a name="函数类型" class="anchor" href="#函数类型"><span class="header-link"></span></a>函数类型</h2><h3 class="section-title"><a name="给函数添加类型" class="anchor" href="#给函数添加类型"><span class="header-link"></span></a>给函数添加类型</h3><div role="item"><p>让我们给前面的例子加上类型：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Let&#39;s add types to our simple examples from earlier:
</p></div><pre><code class="lang-js">function add(x: number, y: number): number {
    return x+y;
}

var myAdd = function(x: number, y: number): number { return x+y; };
</code></pre>
<div role="item"><p>我们可以给函数的每个参数和返回值指定类型。TypeScript可以通过返回的语句知道返回值的类型。所以在很多情况下，我们也可以不指定类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">We can add types to each of the parameters and then to the function itself to add a return type. TypeScript can figure the return type out by looking at the return statements, so we can also optionally leave this off in many cases.
</p></div><h3 class="section-title"><a name="书写函数类型" class="anchor" href="#书写函数类型"><span class="header-link"></span></a>书写函数类型</h3><div role="item"><p>既然我们已经给函数定义了类型，现在让我们完整地写出这个函数各个部分的类型：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Now that we&#39;ve typed the function, let&#39;s write the full type of the function out by looking at the each piece of the function type. 
</p></div><pre><code class="lang-js">var myAdd: (x:number, y:number)=&gt;number = 
    function(x: number, y: number): number { return x+y; };
</code></pre>
<div role="item"><p>一个函数上的类型包含两个部分：参数的类型和返回值的类型。如果我们想要完整地写出函数的类型的话，那这两部分都将是必不可少的。我们给每个参数一个名称和类型，罗列出它们。因为参数的名称只是为了程序的可读性，所以我们也可以这么写上面的例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">A function&#39;s type has the same two parts: the type of the arguments and the return type. When writing out the whole function type, both parts are required. We write out the parameter types just like a parameter list, giving each parameter a name and a type. This name is just to help with readability. We could have instead written:
</p></div><pre><code class="lang-js">var myAdd: (baseValue:number, increment:number)=&gt;number = 
    function(x: number, y: number): number { return x+y; };
</code></pre>
<div role="item"><p>不管你给函数的参数取了什么名字，只要你列出了这个参数的类型，那它对函数来说就是有效的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">As long as the parameter types line up, it&#39;s considered a valid type for the function, regardless of the names you give the parameters in the function type. 
</p></div><div role="item"><p>让我们再来看看返回值的类型。我们通过在参数和返回值的类型之间使用&#39;=&gt;&#39;符号来指定一个函数返回值的类型。如果一个函数不返回值的话，我们需要使用&#39;void&#39;类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The second part is the return type. We make it clear which is the return type by using a fat arrow (=&gt;) between the parameters and the return type. As mentioned before, this is a required part of the function type, so if the function doesn&#39;t return a value, you would use &#39;void&#39; instead of leaving it off.
</p></div><div role="item"><p>记住，参数类型和返回值的类型共同构成了函数的类型。函数中被捕获的变量并不会影响函数的类型。这些变量实际上是被当作函数的&#39;隐藏状态&#39;，它们并不会成为函数API的一部分。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Of note, only the parameters and the return type make up the function type. Captured variables are not reflected in the type. In effect, captured variables are part of the &#39;hidden state&#39; of any function and do not make up its API.
</p></div><h3 class="section-title"><a name="推断类型" class="anchor" href="#推断类型"><span class="header-link"></span></a>推断类型</h3><div role="item"><p>通过前面的例子你可能注意到了，虽然等号的一边有指定类型而另一边没有，但TypeScript的编译器仍能够理解这二者的类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In playing with the example, you may notice that the TypeScript compiler can figure out the type if you have types on one side of the equation but not the other:
</p></div><pre><code class="lang-js">// myAdd has the full function type
var myAdd = function(x: number, y: number): number { return x+y; };

// The parameters &#39;x&#39; and &#39;y&#39; have the type number
var myAdd: (baseValue:number, increment:number)=&gt;number = 
    function(x, y) { return x+y; };
</code></pre>
<div role="item"><p>这种类型被称作&#39;语境类型&#39;（&#39;contextual typing&#39;），是一种类型推断。它有助于减少我们维护类型的工作。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">This is called &#39;contextual typing&#39;, a form of type inference. This helps cut down on the amount of effort to keep your program typed.
</p></div><h2 class="section-title"><a name="可选参数和默认参数" class="anchor" href="#可选参数和默认参数"><span class="header-link"></span></a>可选参数和默认参数</h2><div role="item"><p>与JavaScript不同，TypeScript函数中的每个参数都被认为是必须的。但这并不是说参数的值不能是&#39;null&#39;，只是当一个函数被调用时，编译器会检查用户提供的参数。编译器同样也会假设这些参数是传入函数的唯一参数。简而言之，我们必须保证传给函数的参数的数量和函数指定的参数数量是一致的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Unlike JavaScript, in TypeScript every parameter to a function is assumed to be required by the function. This doesn&#39;t mean that it isn&#39;t a &#39;null&#39; value, but rather, when the function is called the compiler will check that the user has provided a value for each parameter. The compiler also assumes that these parameters are the only parameters that will be passed to the function. In short, the number of parameters to the function has to match the number of parameters the function expects.
</p></div><pre><code class="lang-js">function buildName(firstName: string, lastName: string) {
    return firstName + &quot; &quot; + lastName;
}

var result1 = buildName(&quot;Bob&quot;);  //error, too few parameters
var result2 = buildName(&quot;Bob&quot;, &quot;Adams&quot;, &quot;Sr.&quot;);  //error, too many parameters
var result3 = buildName(&quot;Bob&quot;, &quot;Adams&quot;);  //ah, just right
</code></pre>
<div role="item"><p>在JavaScript中，每个参数被认为是可选的。用户可以按照自己的意愿去掉一部分参数，而没有被传入的参数会被当成是undefined。在TypeScript中，我们可以在一个参数的旁边使用&#39;?&#39;符号来指定这个参数是可选的。举例来说，如果我们想要last name是可选的话：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In JavaScript, every parameter is considered optional, and users may leave them off as they see fit. When they do, they&#39;re assumed to be undefined. We can get this functionality in TypeScript by using the &#39;?&#39; beside parameters we want optional. For example, let&#39;s say we want the last name to be optional:
</p></div><pre><code class="lang-js">function buildName(firstName: string, lastName?: string) {
    if (lastName)
        return firstName + &quot; &quot; + lastName;
    else
        return firstName;
}

var result1 = buildName(&quot;Bob&quot;);  //works correctly now
var result2 = buildName(&quot;Bob&quot;, &quot;Adams&quot;, &quot;Sr.&quot;);  //error, too many parameters
var result3 = buildName(&quot;Bob&quot;, &quot;Adams&quot;);  //ah, just right
</code></pre>
<div role="item"><p>可选参数必须放在必选参数的后面。前面的例子中，如果我们想要first name是可选的，而last name是必选的话，我们就需要把first name放在后面。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Optional parameters must follow required parameters. Had we wanted to make the first name optional rather than the last name, we would need to change the order of parameters in the function, putting the first name last in the list.
</p></div><div role="item"><p>在TypeScript中，我们也可以设置一个值，用作用户没有传入参数时的默认值。这种参数被称作默认参数（default parameters）。下面的例子把前面例子中的last name的默认值改为了&quot;Smith&quot;。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In TypeScript, we can also set up a value that an optional parameter will have if the user does not provide one. These are called default parameters. Let&#39;s take the previous example and default the last name to &quot;Smith&quot;.
</p></div><pre><code class="lang-js">function buildName(firstName: string, lastName = &quot;Smith&quot;) {
    return firstName + &quot; &quot; + lastName;
}

var result1 = buildName(&quot;Bob&quot;);  //works correctly now, also
var result2 = buildName(&quot;Bob&quot;, &quot;Adams&quot;, &quot;Sr.&quot;);  //error, too many parameters
var result3 = buildName(&quot;Bob&quot;, &quot;Adams&quot;);  //ah, just right
</code></pre>
<div role="item"><p>和可选参数一样，默认参数必须出现在必选参数的后面。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Just as with optional parameters, default parameters must come after required parameters in the parameter list. 
</p></div><div role="item"><p>可选参数和默认参数会共享数据类型。下面的：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Optional parameters and default parameters also share what the type looks like. Both:
</p></div><pre><code class="lang-js">function buildName(firstName: string, lastName?: string) {
</code></pre>
<div role="item"><p>和<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">and
</p></div><pre><code class="lang-js">function buildName(firstName: string, lastName = &quot;Smith&quot;) {
</code></pre>
<div role="item"><p>享有同样的类型&quot;(firstName: string, lastName?: string)=&gt;string&quot;。默认参数的的默认值不会生效，它表明了这个参数是可选的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">share the same type &quot;(firstName: string, lastName?: string)=&gt;string&quot;. The default value of the default parameter disappears, leaving only the knowledge that the parameter is optional.
</p></div><h2 class="section-title"><a name="剩余参数" class="anchor" href="#剩余参数"><span class="header-link"></span></a>剩余参数</h2><div role="item"><p>必选参数，可选参数和默认参数有一个共同点：这些参数一次只描述一个参数。有时候你可能希望把多个参数设成一组，或者你没法确定一个函数最终会有多少个参数。在JavaScript中处理这些情况时，你可以直接使用函数体中可以获取的arguments来获得每一个参数。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Required, optional, and default parameters all have one thing in common: they&#39;re about talking about one parameter at a time. Sometimes, you want to work with multiple parameters as a group, or you may not know how many parameters a function will ultimately take. In JavaScript, you can work with the arguments direction using the arguments variable that is visible inside every function body.
</p></div><div role="item"><p>而在TypeScript中，你可以把这些参数聚集到一个变量中：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In TypeScript, you can gather these arguments together into a variable:
</p></div><pre><code class="lang-js">function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + &quot; &quot; + restOfName.join(&quot; &quot;);
}

var employeeName = buildName(&quot;Joseph&quot;, &quot;Samuel&quot;, &quot;Lucas&quot;, &quot;MacKinzie&quot;);
</code></pre>
<div role="item"><p>剩余参数（rest parameters）可以包含多个可选参数。你可以按你的意愿随意使用这些参数。编译器会把传入函数的参数放入一个以省略号（...）开头为名字的变量之中，以供你在函数中使用。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Rest parameters are treated as a boundless number of optional parameters. You may leave them off, or have as many as you want. The compiler will build an array of the arguments you pass to the function under the name given after the ellipsis (...), allowing you to use it in your function. 
</p></div><div role="item"><p>同时省略号也可以用在带有剩余参数的函数上：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The ellipsis is also used in the type of the function with rest parameters:
</p></div><pre><code class="lang-js">function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + &quot; &quot; + restOfName.join(&quot; &quot;);
}

var buildNameFun: (fname: string, ...rest: string[])=&gt;string = buildName;
</code></pre>
<h2 class="section-title"><a name="Lambdas和&#39;this&#39;的使用" class="anchor" href="#Lambdas和&#39;this&#39;的使用"><span class="header-link"></span></a>Lambdas和&#39;this&#39;的使用</h2><div role="item"><p>学习&#39;this&#39;在函数中的工作方式几乎是每一个学习JavaScript的编码人员的必修课。实际对&#39;this&#39;的学习也是开发者习惯使用JavaScript的一个重要过程。而TypeScript是JavaScript超集，它要求开发人员在懂得如何使用&#39;this&#39;的同时，也能够发现代码中没有被正确使用的&#39;this&#39;。关于JavaScript中的&#39;this&#39;完全足够写一篇文章了，并且实际上也有很多人这么干了。这里我们只关注一些基本的东西。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">How &#39;this&#39; works in JavaScript functions is a common theme in programmers coming to JavaScript. Indeed, learning how to use it is something of a rite of passage as developers become more accustomed to working in JavaScript. Since TypeScript is a superset of JavaScript, TypeScript developers also need to learn how to use &#39;this&#39; and how to spot when it&#39;s not being used correctly. A whole article could be written on how to use &#39;this&#39; in JavaScript, and many have. Here, we&#39;ll focus on some of the basics. 
</p></div><div role="item"><p>JavaScript中的函数在被调用时会设置一个&#39;this&#39;变量。虽然这个特性强大而又灵活，但使用这个特性却需要我们时刻关注函数执行的环境。举例来说，当我们在回调函数上执行一个函数时，这个函数的上下文环境就会变得难以预料。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In JavaScript, &#39;this&#39; is a variable that&#39;s set when a function is called. This makes it a very powerful and flexible feature, but it comes at the cost of always having to know about the context that a function is executing in. This can be notoriously confusing, when, for example, when a function is used as a callback.
</p></div><div role="item"><p>让我们看一个例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Let&#39;s look at an example:
</p></div><pre><code class="lang-js">var deck = {
    suits: [&quot;hearts&quot;, &quot;spades&quot;, &quot;clubs&quot;, &quot;diamonds&quot;],
    cards: Array(52),
    createCardPicker: function() {
        return function() {
            var pickedCard = Math.floor(Math.random() * 52);
            var pickedSuit = Math.floor(pickedCard / 13);

            return {suit: this.suits[pickedSuit], card: pickedCard % 13};
        }
    }
}

var cardPicker = deck.createCardPicker();
var pickedCard = cardPicker();

alert(&quot;card: &quot; + pickedCard.card + &quot; of &quot; + pickedCard.suit);
</code></pre>
<div role="item"><p>虽然看起来这段代码会返回一个警告框，但实际上我们只会得到一个错误提示。因为&#39;createCardPicker&#39;创建的函数上的&#39;this&#39;指向的是&#39;window&#39;而不是&#39;deck&#39;对象。执行&#39;cardPicker()&#39;就会产生这样的结果。这里的&#39;this&#39;只能被动态绑定到&#39;window&#39;上（记住：在严格模式下，这里的&#39;this&#39;的值会是&#39;undefined&#39;而不是&#39;window&#39;）。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">If we tried to run the example, we would get an error instead of the expected alert box. This is because the &#39;this&#39; being used in the function created by &#39;createCardPicker&#39; will be set to &#39;window&#39; instead of our &#39;deck&#39; object. This happens as a result of calling &#39;cardPicker()&#39;. Here, there is no dynamic binding for &#39;this&#39; other than Window. (note: under strict mode, this will be undefined rather than window).
</p></div><div role="item"><p>要解决这一问题，我们就要保证这个函数在被调用之前是被绑定到了正确的&#39;this&#39;对象上。不管这个函数之后会被如何调用，只要我们正确地进行了绑定，这个函数就总能获得原始的&#39;deck&#39;对象。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">We can fix this by making sure the function is bound to the correct &#39;this&#39; before we return the function to be used later. This way, regardless of how its later used, it will still be able to see the original &#39;deck&#39; object.
</p></div><div role="item"><p>这里我们用lambda句法（lambda syntax，()=&gt;{}）来代替JavaScript的函数表达式，以解决这个问题。它不是在函数被触发时寻找&#39;this&#39;的对象，而是在函数被创建时就自动捕获&#39;this&#39;指代的对象。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To fix this, we switching the function expression to use the lambda syntax ( ()=&gt;{} ) rather than the JavaScript function expression. This will automatically capture the &#39;this&#39; available when the function is created rather than when it is invoked:
</p></div><pre><code class="lang-js">var deck = {
    suits: [&quot;hearts&quot;, &quot;spades&quot;, &quot;clubs&quot;, &quot;diamonds&quot;],
    cards: Array(52),
    createCardPicker: function() {
        // Notice: the line below is now a lambda, allowing us to capture &#39;this&#39; earlier
        return () =&gt; {
            var pickedCard = Math.floor(Math.random() * 52);
            var pickedSuit = Math.floor(pickedCard / 13);

            return {suit: this.suits[pickedSuit], card: pickedCard % 13};
        }
    }
}

var cardPicker = deck.createCardPicker();
var pickedCard = cardPicker();

alert(&quot;card: &quot; + pickedCard.card + &quot; of &quot; + pickedCard.suit);
</code></pre>
<div role="item"><p>你可以阅读Yahuda Katz的Understanding JavaScript Function Invocation and “this”来获取更多的信息。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">For more information on ways to think about &#39;this&#39;, you can read Yahuda Katz&#39;s Understanding JavaScript Function Invocation and “this”.
</p></div><h2 class="section-title"><a name="重载" class="anchor" href="#重载"><span class="header-link"></span></a>重载</h2><div role="item"><p>JavaScript本质上是一门动态性极强的语言。一个JavaScript函数可以根据传入参数的类型和数量来返回不同类型的对象，并且这样的使用方式并不少见。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">JavaScript is inherently a very dynamic language. It&#39;s not uncommon for a single JavaScript function to return different types of objects based on the shape of the arguments passed in. 
</p></div><pre><code class="lang-js">var suits = [&quot;hearts&quot;, &quot;spades&quot;, &quot;clubs&quot;, &quot;diamonds&quot;];

function pickCard(x): any {
    // Check to see if we&#39;re working with an object/array
    // if so, they gave us the deck and we&#39;ll pick the card
    if (typeof x == &quot;object&quot;) {
        var pickedCard = Math.floor(Math.random() * x.length);
        return pickedCard;
    }
    // Otherwise just let them pick the card
    else if (typeof x == &quot;number&quot;) {
        var pickedSuit = Math.floor(x / 13);
        return { suit: suits[pickedSuit], card: x % 13 };
    }
}

var myDeck = [{ suit: &quot;diamonds&quot;, card: 2 }, { suit: &quot;spades&quot;, card: 10 }, { suit: &quot;hearts&quot;, card: 4 }];
var pickedCard1 = myDeck[pickCard(myDeck)];
alert(&quot;card: &quot; + pickedCard1.card + &quot; of &quot; + pickedCard1.suit);

var pickedCard2 = pickCard(15);
alert(&quot;card: &quot; + pickedCard2.card + &quot; of &quot; + pickedCard2.suit);
</code></pre>
<div role="item"><p>这里的&#39;pickCard&#39;函数会根据用户传入参数的不同来返回两种不同的结果。如果用户传入的是一个表示&#39;deck&#39;的对象，那这个函数就会返回&#39;pickedCard&#39;；如果用户要选择一张card，这个函数就会告诉用户card的结果。那么我们要如何用类型系统来描述这种情景呢？<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Here the &#39;pickCard&#39; function will return two different things based on what the user has passed in. If the users passes in an object that represents the deck, the function will pick the card. If the user picks the card, we tell them which card they&#39;ve picked. But how do we describe this to the type system.
</p></div><div role="item"><p>答案是用一个重载列表来描述函数的多个类型。编译器会用这个列表来处理函数调用。现在让我们用一个重载列表来描述&#39;pickCard&#39;所接收的参数和返回的类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The answer is to supply multiple function types for the same function as a list of overloads. This list is what the compiler will use to resolve function calls. Let&#39;s create a list of overloads that describe what our &#39;pickCard&#39; accepts and what it returns.
</p></div><pre><code class="lang-js">var suits = [&quot;hearts&quot;, &quot;spades&quot;, &quot;clubs&quot;, &quot;diamonds&quot;];

function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): any {
    // Check to see if we&#39;re working with an object/array
    // if so, they gave us the deck and we&#39;ll pick the card
    if (typeof x == &quot;object&quot;) {
        var pickedCard = Math.floor(Math.random() * x.length);
        return pickedCard;
    }
    // Otherwise just let them pick the card
    else if (typeof x == &quot;number&quot;) {
        var pickedSuit = Math.floor(x / 13);
        return { suit: suits[pickedSuit], card: x % 13 };
    }
}

var myDeck = [{ suit: &quot;diamonds&quot;, card: 2 }, { suit: &quot;spades&quot;, card: 10 }, { suit: &quot;hearts&quot;, card: 4 }];
var pickedCard1 = myDeck[pickCard(myDeck)];
alert(&quot;card: &quot; + pickedCard1.card + &quot; of &quot; + pickedCard1.suit);

var pickedCard2 = pickCard(15);
alert(&quot;card: &quot; + pickedCard2.card + &quot; of &quot; + pickedCard2.suit);
</code></pre>
<div role="item"><p>通过过载，我们现在就可以对&#39;pickCard&#39;函数进行类型检查了。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">With this change, the overloads now give us type-checked calls to the &#39;pickCard&#39; function. 
</p></div><div role="item"><p>编译器在进行类型检查时，其处理方式与普通的JavaScript相似。编译器会查看重载列表，并尝试与函数调用时的参数进行匹配。编译器会把第一个成功匹配的过载认做是正确的一个。也因为如此，我们需要把重载按照从最详细的到最粗略的顺序进行排序。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In order for the compiler to pick the correct typecheck, it follows a similar process to the underlying JavaScript. It looks at the overload list, and proceeding with the first overload attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload. For this reason, its customary to order overloads from most specific to least specific.
</p></div><div role="item"><p>注意&#39;function pickCard(x): any&#39;并不会成为过载列表的一部分，即这个函数只有两个过载：其中一个重载以一个对象作为参数，另一个以一个数字作为参数。以任何其他的参数调用&#39;pickCard&#39;都会产生错误。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Note that the &#39;function pickCard(x): any&#39; piece is not part of the overload list, so it only has two overloads: one that takes an object and one that takes a number. Calling &#39;pickCard&#39; with any other parameter types would cause an error.
</p></div><hr>
<h1 class="section-title"><a name="泛型" class="anchor" href="#泛型"><span class="header-link"></span></a>泛型</h1><div role="item"><p>构建部件是软件工程重要的一部分。这些部件不仅要有精心设计过的，高一致性的API，同时也要具有复用性。如果我们构建的部件不仅能够满足现在的需求，并且也能够应对未来的变化，那我们在构建大型系统时就能够更加地游刃有余。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">A major part of software engineering is building components that not only have well-defined and consistent APIs, but are also reusable. Components that are capable of working on the data of today as well as the data of tomorrow will give you the most flexible capabilities for building up large software systems.
</p></div><div role="item"><p>在C#和Java这样的语言中创建可重用的部件时，我们最常用的工具之一便是泛型(&#39;generics&#39;)。它允许我们创建一个可同时作用在多种数据类型上的部件。这就使得用户在使用这些部件时可以用它们自己定义的类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In languages like C# and Java, one of the main tools in the toolbox for creating reusable components is &#39;generics&#39;, that is, being able to create a component that can work over a variety of types rather than a single one. This allows users to consume these components and use their own types.
</p></div><h2 class="section-title"><a name="泛型中的Hello World" class="anchor" href="#泛型中的Hello World"><span class="header-link"></span></a>泛型中的Hello World</h2><div role="item"><p>让我们用泛型中的&quot;hello world&quot; —— identity函数来作为开始的例子。这个identity函数可以返回传入给它的任何类型的参数。你可以把它想成是&#39;echo&#39;命令。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To start off, let&#39;s do the &quot;hello world&quot; of generics: the identity function. The identity function is a function that will return back whatever is passed in. You can think of this in a similar way to the &#39;echo&#39; command. 
</p></div><div role="item"><p>如果不使用泛型的话，我们要么得给identity函数一个特定的类型：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Without generics, we would either have to give the identity function a specific type:
</p></div><pre><code class="lang-js">function identity(arg: number): number {
    return arg;
}
</code></pre>
<div role="item"><p>要么用&#39;any&#39;类型：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Or, we could describe the identity function using the &#39;any&#39; type:
</p></div><pre><code class="lang-js">function identity(arg: any): any {
    return arg;
}
</code></pre>
<div role="item"><p>虽然用&#39;any&#39;类型时，我们的函数也能够接收各种类型的&#39;arg&#39;，这样看起来也是泛用的。但实际上我们失去了函数返回时的类型信息。比如我们传入一个数字，但我们只能知道函数返回的是&#39;any&#39;类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">While using &#39;any&#39; is certainly generic in that will accept any and all types for the type of &#39;arg&#39;, we actually are losing the information about what that type was when the function returns. If we passed in a number, the only information we have is that any type could be returned. 
</p></div><div role="item"><p>取而代之的，我们需要有一种方式能够获取参数类型，并用这个类型作为函数返回值的类型。这里我们将使用一种特别的变量——类型变量。它只对类型起作用而不对值起作用。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Instead, we need a way of capturing the type of the argument in such a way that we can also use it to denote what is being returned. Here, we will use a type variable, a special kind of variable that works on types rather than values. 
</p></div><pre><code class="lang-js">function identity&lt;T&gt;(arg: T): T {
    return arg;
}
</code></pre>
<div role="item"><p>我们现在要给identity函数添加一个类型变量&#39;T&#39;。通过这个&#39;T&#39;我们能够获取用户提供的数据类型（比如：number），然后我们就能在函数中使用这个类型。这里我们把&#39;T&#39;用在函数返回值的类型上。这样在看代码时，我们就知道参数的类型和函数返回的类型是一样的，TypeScript就可以在函数的内部或外部使用这个函数的类型信息。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">We&#39;ve now added a type variable &#39;T&#39; to the identity function. This &#39;T&#39; allows us to capture the type the user provides (eg, number), so that we can use that information later. Here, we use &#39;T&#39; again as the return type. On inspection, we can now see the same type is used for the argument and the return type. This allows us to traffic that type information in one side of the function and out the other.
</p></div><div role="item"><p>因为这个版本的&#39;identity&#39;函数可以用在多种类型上，所以我们说它是泛用的（generic）。但这又不同于使用&#39;any&#39;的函数，因为它仍旧保留了准确的类型信息。它能够像我们的第一个&#39;identity&#39;函数那样把number作为参数类型和函数返回值类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">We say that this version of the &#39;identity&#39; function is generic, as it works over a range of types. Unlike using &#39;any&#39;, it&#39;s also just as precise (ie, it doesn&#39;t lose any information) as the first &#39;identity&#39; function that used numbers for the argument and return type.
</p></div><div role="item"><p>定义完identity的泛型后，我们就可以通过两种方式来调用它。一种是传入所有的参数给函数，包括类型参数：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Once we&#39;ve written the generic identity function, we can call it in one of two ways. The first way is to pass all of the arguments, including the type argument, to the function:
</p></div><pre><code class="lang-js">var output = identity&lt;string&gt;(&quot;myString&quot;);  // type of output will be &#39;string&#39;
</code></pre>
<div role="item"><p>这里我们把&#39;T&#39;设置为string（string同时也是传入函数的参数的类型）。类型变量要用&lt;&gt;而非()来包裹。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Here we explicitly set &#39;T&#39; to be string as one of the arguments to the function call, denoted using the &lt;&gt; around the arguments rather than ().
</p></div><div role="item"><p>第二种方法可能更常见，即类型参数推断（type argument inference）。编译器会根据传入参数的类型来自动地设置T的值：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The second way is also perhaps the most common. Here we use /type argument inference/, that is, we want the compiler to set the value of T for us automatically based on the type of the argument we pass in:
</p></div><pre><code class="lang-js">var output = identity(&quot;myString&quot;);  // type of output will be &#39;string&#39;
</code></pre>
<div role="item"><p>注意这里我们没有显式地用尖括号(&lt;&gt;)来传入类型，编译会根据&quot;myString&quot;来设置类型。类型参数推断在保持代码的简短和可读性上很有用，但在很多复杂的情况下编译器无法推测出类型。这时候我们就需要明确地定义泛型的类型了。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Notice that we didn&#39;t have explicitly pass the type in the angle brackets (&lt;&gt;), the compiler just looked at the value &quot;myString&quot;, and set T to its type. While type argument inference can be a helpful tool to keep code shorter and more readable, you may need to explicitly pass in the type arguments as we did in the previous example when the compiler fails to infer the type, as may happen in more complex examples.
</p></div><h2 class="section-title"><a name="使用泛型类型变量" class="anchor" href="#使用泛型类型变量"><span class="header-link"></span></a>使用泛型类型变量</h2><div role="item"><p>开始用泛型时你会注意到，创建像&#39;identity&#39;这样的泛型函数时，编译器会强制要求你在函数体中正确地使用泛型类型的参数。就是说，你需要明确这些参数的类型是任意的，并对其进行相应的处理。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When you begin to use generics, you&#39;ll notice that when you create generic functions like &#39;identity&#39;, the compiler will enforce that you use any generically typed parameters in the body of the function correctly. That is, that you actually treat these parameters as if they could be any and all types.
</p></div><div role="item"><p>让我们看看前面的&#39;identity&#39;函数：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Let&#39;s take our &#39;identity&#39; function from earlier:
</p></div><pre><code class="lang-js">function identity&lt;T&gt;(arg: T): T {
    return arg;
}
</code></pre>
<div role="item"><p>假如你想要在每次调用时获得&#39;arg&#39;的长度的话，你可能会自觉地写成这样：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">What if want to also log the length of the argument &#39;arg&#39; to the console with each call. We might be tempted to write this:
</p></div><pre><code class="lang-js">function loggingIdentity&lt;T&gt;(arg: T): T {
    console.log(arg.length);  // Error: T doesn&#39;t have .length
    return arg;
}
</code></pre>
<div role="item"><p>如果你这么写了的话，编译器就会报错说你尝试在&#39;arg&#39;上使用&#39;.length&#39;，但却没有在任何地方声明过&#39;arg&#39;的这个成员。刚才我们说过这些类型变量可能会是任何类型的变量，使用这个函数的人可能会传入一个&#39;number&#39;类型，这样的这个参数就没有&#39;.length&#39;成员了。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When we do, the compiler will give us an error that we&#39;re using the &quot;.length&quot; member of &#39;arg&#39;, but nowhere have we said that &#39;arg&#39; has this member. Remember, we said earlier that these type variables stand in for any and all types, so someone using this function could have passed in a &#39;number&#39; instead, which does not have a &quot;.length&quot; member. 
</p></div><div role="item"><p>假设我们实际上希望这个泛型函数是以T的数组而不是直接以T来运行的，那么我们可以将参数描述成类型的数组，这样我们就可以获得&#39;.length成员了：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Let&#39;s say that we&#39;ve actually intended this function to work on arrays of T rather that T directly. Since we&#39;re working with arrays, the .length member should be available. We can describe this just like we would create arrays of other types:
</p></div><pre><code class="lang-js">function loggingIdentity&lt;T&gt;(arg: T[]): T[] {
    console.log(arg.length);  // Array has a .length, so no more error
    return arg;
}
</code></pre>
<div role="item"><p>你可以把logging Identity的类型认为是logginIdentity泛型。它需要一个类型参数T，一个T类型的数组参数&#39;arg&#39;，它最终返回的是T类型的一个数组。如果我们给泛型传入一个数字组成的数组，它就会把T类型绑定成数字，并返回一个数字类型的数组。也就是说现在我们可以使用泛型变量T作为我们可使用类型的一部分，而不是使用参数的整个类型。这让我们能够根据实际情况进行更加灵活的处理。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">You can read the type of logging Identity as &quot;the generic function loggingIdentity, takes a type parameter T, and an argument &#39;arg&#39; which is an array of these T&#39;s, and returns an array of T&#39;s. If we passed in an array of numbers, we&#39;d get an array of numbers back out, as T would bind to number. This allows us to use our generic type variable &#39;T&#39; as part of the types we&#39;re working with, rather than the whole type, giving us greater flexibility. 
</p></div><div role="item"><p>我们也可以把它写成这样：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">We can alternatively write the sample example this way:
</p></div><pre><code class="lang-js">function loggingIdentity&lt;T&gt;(arg: Array&lt;T&gt;): Array&lt;T&gt; {
    console.log(arg.length);  // Array has a .length, so no more error
    return arg;
}
</code></pre>
<div role="item"><p>如果你接触过其他语言的话，你可能已经很熟悉这种类型的写法了。我们将在下一部分中讲到如何创建Array<T>这样的泛型类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">You may already be familiar with this style of type from other languages. In the next section, we&#39;ll cover how you can create your own generic types like Array<T>.
</p></div><h2 class="section-title"><a name="泛型类型" class="anchor" href="#泛型类型"><span class="header-link"></span></a>泛型类型</h2><div role="item"><p>在上一部分中，我们创建了可以与多种类型进行工作的identity泛型函数。在这一部分中，我们将探索函数本身的类型以及泛型接口的创建。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In previous sections, we created generic identity functions that worked over a range of types. In this section, we&#39;ll explore the type of the functions themselves and how to create generic interfaces.
</p></div><div role="item"><p>在泛型函数中我们需要先把类型参数列举出来，就像其他的非泛型函数的定义方式一样。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The type of generic functions is just like those of non-generic functions, with the type parameters listed first, similarly to function declarations:
</p></div><pre><code class="lang-js">function identity&lt;T&gt;(arg: T): T {
    return arg;
}

var myIdentity: &lt;T&gt;(arg: T)=&gt;T = identity;
</code></pre>
<div role="item"><p>我们也可以给泛型的类型参数一个不同的名称，我们只需要明确地表示出类型变量的数量和它们的使用方式。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">We could also have used a different name for the generic type parameter in the type, so long as the number of type variables and how the type variables are used line up.
</p></div><pre><code class="lang-js">function identity&lt;T&gt;(arg: T): T {
    return arg;
}

var myIdentity: &lt;U&gt;(arg: U)=&gt;U = identity;
</code></pre>
<div role="item"><p>我们也可以像描述对象一样来描述泛型的类型：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">We can also write the generic type as a call signature of an object literal type:
</p></div><pre><code class="lang-js">function identity&lt;T&gt;(arg: T): T {
    return arg;
}

var myIdentity: {&lt;T&gt;(arg: T): T} = identity;
</code></pre>
<div role="item"><p>让我们遵循这种写法来写我们的第一个泛型接口。让我们把前面例子中像是在声明对象一样的部分移到一个接口中：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Which leads us to writing our first generic interface. Let&#39;s take the object literal from the previous example and move it to an interface:
</p></div><pre><code class="lang-js">interface GenericIdentityFn {
    &lt;T&gt;(arg: T): T;
}

function identity&lt;T&gt;(arg: T): T {
    return arg;
}

var myIdentity: GenericIdentityFn = identity;
</code></pre>
<div role="item"><p>类似地，我们可能会想把这个泛型参数独立出来，作为整个接口的一个参数。这样我们就可以知道我们泛型接口的类型参数了（即Dictionary<string>而不是Dictionary）。这也可以使得接口的类型参数对其他成员可见。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In a similar example, we may want to move the generic parameter to be a parameter of the whole interface. This lets us see what type(s) we&#39;re generic over (eg Dictionary<string> rather than just Dictionary). This makes the type parameter visible to all the other members of the interface. 
</p></div><pre><code class="lang-js">interface GenericIdentityFn&lt;T&gt; {
    (arg: T): T;
}

function identity&lt;T&gt;(arg: T): T {
    return arg;
}

var myIdentity: GenericIdentityFn&lt;number&gt; = identity;
</code></pre>
<div role="item"><p>注意到现在我们的例子已经变得跟前面有些不同了。我们现在用一个非泛型函数的标识作为一个泛型类型的一部分，而不是直接描述一个泛型函数。我们在使用GenericIdentityFn时也需要指定一个对应的类型参数（这里是number）。这种做法可以有效地限制各种潜在的调用情况。如果我们想要更好地描述一个类型的泛用范围的话，我们就需要明确在调用时，何时应该直接使用类型参数，何时应该要把类型参数放在接口上。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Notice that our example has changed to be something slightly different. Instead of describing a generic function, we now have a non-generic function signature that is a part of a generic type. When we use GenericIdentityFn, we now will also need to specify the corresponding type argument (here: number), effectively locking in what the underlying call signature will use. Understanding when to put the type parameter directly on the call signature and when to put it on the interface itself will be helpful in describing what aspects of a type are generic.
</p></div><div role="item"><p>除了泛型接口，我们也可以创建泛型类。但我们无法为枚举和模块创建泛型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In addition to generic interfaces, we can also create generic classes. Note that it is not possible to create generic enums and modules.
</p></div><h2 class="section-title"><a name="泛型类" class="anchor" href="#泛型类"><span class="header-link"></span></a>泛型类</h2><div role="item"><p>泛型类与泛型接口的结构相似。泛型类会有泛型类型参数列表，这个列表是在类名后面以尖括号（&lt;&gt;）定义。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">A generic class has a similar shape to a generic interface. Generic classes have a generic type parameter list in angle brackets (&lt;&gt;) following the name of the class.
</p></div><pre><code class="lang-js">class GenericNumber&lt;T&gt; {
    zeroValue: T;
    add: (x: T, y: T) =&gt; T;
}

var myGenericNumber = new GenericNumber&lt;number&gt;();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
</code></pre>
<div role="item"><p>上面例子中的&#39;GenericNumber&#39;类是一个非常典型的使用情景。但你可能也注意到了这个泛型类本身并没有限制自己只供&#39;number&#39;类型使用。我们也可在以在其上使用&#39;string&#39;甚至更复杂对象。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">This is a pretty literal use of the &#39;GenericNumber&#39; class, but you may have noticed that nothing is restricting is to only use the &#39;number&#39; type. We could have instead used &#39;string&#39; or even more complex objects.
</p></div><pre><code class="lang-js">var stringNumeric = new GenericNumber&lt;string&gt;();
stringNumeric.zeroValue = &quot;&quot;;
stringNumeric.add = function(x, y) { return x + y; };

alert(stringNumeric.add(stringNumeric.zeroValue, &quot;test&quot;));
</code></pre>
<div role="item"><p>同接口一样，在类上设置类型参数就可以确保这个类所有的属性都是同一类型的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Just as with interface, putting the type parameter on the class itself lets us make sure all of the properties of the class are working with the same type.
</p></div><div role="item"><p>就像前面讲述类时一样，一个类中的类型也可以分成两部分：静态部分和实例部分。而泛型类的&quot;泛型&quot;只是对类的实例部分而言的，就是说当我们在使用泛型类时，静态成员不可以使用类的类型参数。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">As we covered in Classes, a class has two side to its type: the static side and the instance side. Generic classes are only generic over their instance side rather than their static side, so when working with classes, static members can not use the class&#39;s type parameter.
</p></div><h2 class="section-title"><a name="泛型限定" class="anchor" href="#泛型限定"><span class="header-link"></span></a>泛型限定</h2><div role="item"><p>如果你记得我们更早的一个例子的话，你可能会想要写一个专门用于一部分类型的泛型函数。因为你可能知道这些类型的特点，想更好地使用它们。在我们&#39;logginIdentity&#39;的例子中，我们想要获得&#39;arg&#39;参数的&#39;.length&#39;属性。可是编译时编译器会警告我们，因为它不能确定每个类型是否都会有一个&#39;.length&#39;属性，而我们也不能这么假设。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">If you remember from an earlier example, you may sometimes want to write a generic function that works on a set of types where you have some knowledge about what capabilities that set of types will have. In our &#39;loggingIdentity&#39; example, we wanted to be able access the &quot;.length&quot; property of &#39;arg&#39;, but the compiler could not prove that every type had a &quot;.length&quot; property, so it warns us that we can&#39;t make this assumption.
</p></div><pre><code class="lang-js">function loggingIdentity&lt;T&gt;(arg: T): T {
    console.log(arg.length);  // Error: T doesn&#39;t have .length
    return arg;
}
</code></pre>
<div role="item"><p>虽然我们不能在任何可能出现的类型上做这种假设，但我们可以限定函数作用在任何有&#39;.length&#39;属性的类型上。这使得只要一个类型有这个成员，我们就认为这个类型是有效的。想要这样做的话，我么就必须列举出我们对T的需求，并做出限制。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Instead of working with any and all types, we&#39;d like to constrain this function to work with any and all types that also have the &quot;.length&quot; property. As long as the type has this member, we&#39;ll allow it, but it&#39;s required to have at least this member. To do so, we must list our requirement as a constraint on what T can be.
</p></div><div role="item"><p>我们将用一个接口来描述我们的限制。在这里，我们创建了一个有&#39;.length&#39;属性的接口，并用&#39;extends&#39;关键字来使用这个接口。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To do so, we&#39;ll create an interface that describes our constraint. Here, we&#39;ll create an interface that has a single &quot;.length&quot; property and then we&#39;ll use this interface and the extends keyword to denote our constraint:
</p></div><pre><code class="lang-js">interface Lengthwise {
    length: number;
}

function loggingIdentity&lt;T extends Lengthwise&gt;(arg: T): T {
    console.log(arg.length);  // Now we know it has a .length property, so no more error
    return arg;
}
</code></pre>
<div role="item"><p>因为泛型函数被限制了，它现在就不能接收任意类型了：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Because the generic function is now constrained, it will no longer work over any and all types:
</p></div><pre><code class="lang-js">loggingIdentity(3);  // Error, number doesn&#39;t have a .length property
</code></pre>
<div role="item"><p>我们应该传入一个值，它的类型的属性要符合要求：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Instead, we need to pass in values whose type has all the required properties:
</p></div><pre><code class="lang-js">loggingIdentity({length: 10, value: 3});
</code></pre>
<h2 class="section-title"><a name="在泛型限定上使用类型参数" class="anchor" href="#在泛型限定上使用类型参数"><span class="header-link"></span></a>在泛型限定上使用类型参数</h2><div role="item"><p>在某些情况下，声明一个类型参数，并让它被另一个类型参数限制是很有用的，比如：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In some cases, it may be useful to declare a type parameter that is constrained by another type parameter. For example,
</p></div><pre><code class="lang-js">function find&lt;T, U extends Findable&lt;T&gt;&gt;(n: T, s: U) {   // errors because type parameter used in constraint
  // ...
} 
find (giraffe, myAnimals);
</code></pre>
<div role="item"><p>直接限制参数的类型也可以达到同样的效果。我们可以这样重写上面的例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">You can achieve the pattern above by replacing the type parameter with its constraint. Rewriting the example above,
</p></div><pre><code class="lang-js">function find&lt;T&gt;(n: T, s: Findable&lt;T&gt;) {   
  // ...
} 
find(giraffe, myAnimals);
</code></pre>
<div role="item"><p>注意：上面的两个例子并不严格相等。第一个函数返回的类型可以是&#39;U&#39;，而第二个函数并没办法拿到&#39;U&#39;类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Note: The above is not strictly identical, as the return type of the first function could have returned &#39;U&#39;, which the second function pattern does not provide a means to do.
</p></div><h2 class="section-title"><a name="在泛型中使用class类型" class="anchor" href="#在泛型中使用class类型"><span class="header-link"></span></a>在泛型中使用class类型</h2><div role="item"><p>当我们在工厂模式上使用TypeScript的泛型时，构造函数就会涉及到类的类型。举例来说：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When creating factories in TypeScript using generics, it is necessary to refer to class types by their constructor functions. For example,
</p></div><pre><code class="lang-js">function create&lt;T&gt;(c: {new(): T; }): T { 
    return new c();
}
</code></pre>
<div role="item"><p>下面是一个进阶例子。它用原型属性（prototype property）推测并限制构造函数和实例之间类型的关系。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">A more advanced example uses the prototype property to infer and constrain relationships between the constructor function and the instance side of class types.
</p></div><pre><code class="lang-js">class BeeKeeper {
    hasMask: boolean;
}

class ZooKeeper {
    nametag: string; 
}

class Animal {
    numLegs: number;
}

class Bee extends Animal {
    keeper: BeeKeeper;
}

class Lion extends Animal {
    keeper: ZooKeeper;
}

function findKeeper&lt;A extends Animal, K&gt; (a: {new(): A; 
    prototype: {keeper: K}}): K {

    return a.prototype.keeper;
}

findKeeper(Lion).nametag;  // typechecks!
</code></pre>
<hr>
<h1 class="section-title"><a name="常见错误" class="anchor" href="#常见错误"><span class="header-link"></span></a>常见错误</h1><div role="item"><p>下面列举了一些常见的，令人很费解的错误信息。当你在使用TypeScript或进行编译时，也有可能会遇到这些问题。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The list below captures some of the commonly confusing error messages that you may encounter when using the TypeScript language and Compiler
</p></div><h2 class="section-title"><a name="常见错误信息" class="anchor" href="#常见错误信息"><span class="header-link"></span></a>常见错误信息</h2><h3 class="section-title"><a name="&quot;tsc.exe&quot; exited with error code 1." class="anchor" href="#&quot;tsc.exe&quot; exited with error code 1."><span class="header-link"></span></a>&quot;tsc.exe&quot; exited with error code 1.</h3><p><strong>解决办法:</strong>
$check file-encoding is UTF-8 - <a href="https://typescript.codeplex.com/workitem/1587">https://typescript.codeplex.com/workitem/1587</a>
$$检查文件的编码格式是否为UTF-8 - <a href="https://typescript.codeplex.com/workitem/1587">https://typescript.codeplex.com/workitem/1587</a></p>
<h3 class="section-title"><a name="external module XYZ cannot be resolved" class="anchor" href="#external module XYZ cannot be resolved"><span class="header-link"></span></a>external module XYZ cannot be resolved</h3><p><strong>解决办法:</strong>
$check if module path is case-sensitive - <a href="https://typescript.codeplex.com/workitem/2134">https://typescript.codeplex.com/workitem/2134</a>
$$检查模块的路径字母的大小写 - <a href="https://typescript.codeplex.com/workitem/2134">https://typescript.codeplex.com/workitem/2134</a></p>
<hr>
<h1 class="section-title"><a name="混合（Mixins）" class="anchor" href="#混合（Mixins）"><span class="header-link"></span></a>混合（Mixins）</h1><div role="item"><p>在传统的面向对象继承（OO hierarchies）中，通过组合可复用的组件（即一些更简单的类）来构造新的类是非常流行的做法。如果你熟悉像Scala这类语言的话，你对这种做法应该不会陌生。并且这种模式在JavaScript社区中也比较流行。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Along with traditional OO hierarchies, another popular way of building up classes from reusable components is to build them by combining simpler partial classes. You may be familiar with the idea of mixins or traits for languages like Scala, and the pattern has also reached some popularity in the JavaScript community.
</p></div><h2 class="section-title"><a name="Mixin的例子" class="anchor" href="#Mixin的例子"><span class="header-link"></span></a>Mixin的例子</h2><div role="item"><p>在下面的代码中，我们展示了如何在TypeScript中模仿混合的构建方式。我们会在后面讲述它是怎么运作的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In the code below, we show how you can model mixins in TypeScript. After the code, we&#39;ll break down how it works.
</p></div><pre><code class="lang-js">// Disposable Mixin
class Disposable {
    isDisposed: boolean;
    dispose() {
        this.isDisposed = true;
    }

}

// Activatable Mixin
class Activatable {
    isActive: boolean;
    activate() {
        this.isActive = true;
    }
    deactivate() {
        this.isActive = false;
    }
}

class SmartObject implements Disposable, Activatable {
    constructor() {
        setInterval(() =&gt; console.log(this.isActive + &quot; : &quot; + this.isDisposed), 500);
    }

    interact() {
        this.activate();
    }

    // Disposable
    isDisposed: boolean = false;
    dispose: () =&gt; void;
    // Activatable
    isActive: boolean = false;
    activate: () =&gt; void;
    deactivate: () =&gt; void;
}
applyMixins(SmartObject, [Disposable, Activatable])

var smartObj = new SmartObject();
setTimeout(() =&gt; smartObj.interact(), 1000);

////////////////////////////////////////
// In your runtime library somewhere
////////////////////////////////////////

function applyMixins(derivedCtor: any, baseCtors: any[]) {
    baseCtors.forEach(baseCtor =&gt; {
        Object.getOwnPropertyNames(baseCtor.prototype).forEach(name =&gt; {
            derivedCtor.prototype[name] = baseCtor.prototype[name];
        })
    }); 
}
</code></pre>
<h2 class="section-title"><a name="理解这个例子" class="anchor" href="#理解这个例子"><span class="header-link"></span></a>理解这个例子</h2><div role="item"><p>这个例子先定义了两个将要被我们混合的类。你会发现这两个类每个都只关注一种特定的功能或活动。然后我们会把这两个类混合起来来构建一个同时带有这两种功能的新的类。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The code sample starts with the two classes that will act is our mixins. You can see each one is focused on a particular activity or capability. We&#39;ll later mix these together to form a new class from both capabilities.
</p></div><pre><code class="lang-js">// Disposable Mixin
class Disposable {
    isDisposed: boolean;
    dispose() {
        this.isDisposed = true;
    }

}

// Activatable Mixin
class Activatable {
    isActive: boolean;
    activate() {
        this.isActive = true;
    }
    deactivate() {
        this.isActive = false;
    }
}
</code></pre>
<div role="item"><p>接着，我们将创建一个混合了这二者的类。让我们更详细地看看这是如何实现的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Next, we&#39;ll create the class that will handle the combination of the two mixins. Let&#39;s look at this in more detail to see how it does this:
</p></div><pre><code class="lang-js">class SmartObject implements Disposable, Activatable {
</code></pre>
<div role="item"><p>你可能会马上注意到在上面的例子中，我们用&#39;implements&#39;来代替&#39;extends&#39;关键字。这表示我们把这两个类当作是接口。并且与其说我们使用了&#39;Disposable&#39;和&#39;Activatable&#39;的实现，倒不如说是使用了它们的类型。也就是说我们还需要在类中提供这二者的实现。Except, that&#39;s exactly what we want to avoid by using mixins. <span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The first thing you may notice in the above is that instead of using &#39;extends&#39;, we use &#39;implements&#39;. This treats the classes as interfaces, and only uses the types behind Disposable and Activatable rather than the implementation. This means that we&#39;ll have to provide the implementation in class. Except, that&#39;s exactly what we want to avoid by using mixins. 
</p></div><div role="item"><p>为了满足我们的需求，我们要为被混合的类的成员创建替身（stand-in）属性及类型。这使得编译器在运行时可以获得这个类的成员。虽然这种记账式的做法会花费我们些时间，但之后我们就能从mixins中受益了。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To satisfy this requirement, we create stand-in properties and their types for the members that will come from our mixins. This satisfies the compiler that these members will be available at runtime. This lets us still get the benefit of the mixins, albeit with a some bookkeeping overhead.
</p></div><pre><code class="lang-js">// Disposable
isDisposed: boolean = false;
dispose: () =&gt; void;
// Activatable
isActive: boolean = false;
activate: () =&gt; void;
deactivate: () =&gt; void;
</code></pre>
<div role="item"><p>最后，我们把这两个类混合到了一个类中，完整地实现了这个类。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Finally, we mix our mixins into the class, creating the full implementation.
</p></div><pre><code class="lang-js">applyMixins(SmartObject, [Disposable, Activatable])
</code></pre>
<div role="item"><p>我们最后还创建了一个辅助函数来帮我们完成混合的工作。它会查询并复制每个被混合的类的属性，填充实现的类中的每一个属性。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Lastly, we create a helper function that will do the mixing for us. This will run through the properties of each of the mixins and copy them over to the target of the mixins, filling out the stand-in properties with their implementations.
</p></div><pre><code class="lang-js">function applyMixins(derivedCtor: any, baseCtors: any[]) {
    baseCtors.forEach(baseCtor =&gt; {
        Object.getOwnPropertyNames(baseCtor.prototype).forEach(name =&gt; {
            derivedCtor.prototype[name] = baseCtor.prototype[name];
        })
    }); 
}
</code></pre>
<hr>
<h1 class="section-title"><a name="声明合并" class="anchor" href="#声明合并"><span class="header-link"></span></a>声明合并</h1><div role="item"><p>TypeScript上的一些独特的理念，源自我们从类型上描述JavaScript对象结构（shape）变化的需求。TypeScript中独特的&#39;声明合并&#39;（&#39;declaration merging&#39;）就是其中的一个例子。理解这个概念能够帮助你在TypeScript中更好地处理现有的JavaScript代码。同时它也让实现更高级别的抽象成为了可能。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Some of the unique concepts in TypeScript come from the need to describe what is happening to the shape of JavaScript objects at the type level. One example that is especially unique to TypeScript is the concept of &#39;declaration merging&#39;. Understanding this concept will give you an advantage when working with existing JavaScript in your TypeScript. It also opens the door to more advanced abstraction concepts.
</p></div><div role="item"><p>在理解声明是如何合并的之前，先让我们了解到底什么是&#39;声明合并&#39;。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">First, before we get into how declarations merge, let&#39;s first describe what we mean by &#39;declaration merging&#39;.
</p></div><div role="item"><p>在这篇文章中，声明合并特指由编译器完成的，将拥有同样名称的，两个独立的的声明合并成一个定义（a single definition）的工作。这个合并而来的定义将同时拥有原来的两个声明的特性。声明合并不限于合并两个声明，符合条件的任意个声明都可以被合并。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">For the purposes of this article, declaration merging specifically means that the compiler is doing the work of merging two separate declarations declared with the same name into a single definition. This merged definition has the features of both of the original declarations. Declaration merging is not limited to just two declarations, as any number of declarations can be merged.
</p></div><h2 class="section-title"><a name="基本概念" class="anchor" href="#基本概念"><span class="header-link"></span></a>基本概念</h2><div role="item"><p>在TypeScript中，一个声明会来源于下面的三种情况中的一种：命名空间/模块，类型，值。用于创建命名空间/模块的声明可以通过点分隔的表示法获得。用于创建类型的声明会确定一个类型的名称及其结构。第三种创建值的声明在编译输出的JavaScript中可见（如函数和变量）。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In TypeScript, a declaration exists in one of three groups: namespace/module, type, or value. Declarations that create a namespace/module are accessed using a dotted notation when writing a type. Declarations that create a type do just that, create a type that is visible with the declared shape and bound to the given name. Lastly, declarations create a value are those that are visible in the output JavaScript (eg, functions and variables).
</p></div><table>
<tr>
<th>声明类型</th><th>命名空间</th><th>类型</th><th>值</th>
</tr>
<tr>
<td>模块</td><td> X </td><td></td><td> X </td>
</tr>
<tr>
<td>类</td><td></td><td> X </td><td> X </td>
</tr>
<tr>
<td>接口</td><td></td><td> X </td><td></td>
</tr>
<tr>
<td>函数</td><td></td><td></td><td> X </td>
</tr>
<tr>
<td>变量</td><td></td><td></td><td> X </td>
</tr>
</table>

<div role="item"><p>在执行一个声明合并时，理解每个声明到底创建了什么能够帮助你更好地确定到底是什么被合并了。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Understanding what is created with each declaration will help you understand what is merged when you perform a declaration merge.
</p></div><h2 class="section-title"><a name="合并接口" class="anchor" href="#合并接口"><span class="header-link"></span></a>合并接口</h2><div role="item"><p>最简单也最常见的声明合并莫过于接口的合并。在最简单的情况下，这种合并只是机械地把两个同名接口的成员合并到同一个接口中。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The simplest, and perhaps most common, type of declaration merging is interface merging. At the most basic level, the merge mechanically joins the members of both declarations into a single interface with the same name.
</p></div><pre><code class="lang-js">interface Box {
    height: number;
    width: number;
}

interface Box {
    scale: number;
}

var box: Box = {height: 5, width: 6, scale: 10};
</code></pre>
<div role="item"><p>接口的非函数的成员必须是独特的。如果两个接口同时声明了一个有着同样名子的非函数的成员的话，编译器会抛出一个错误。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Non-function members of the interfaces must be unique. The compiler will issue an error if the interfaces both declare a non-function member of the same name.
</p></div><div role="item"><p>而对于函数成员来说，拥有同样名称的每个函数成员都会被当作是同一个函数的重载情况。同样值得注意的是，当一个接口A在融合另一个接口A时（这里称为A&#39;），A&#39;上的重载的集合将会比接口A上的拥有更高优先级。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">For function members, each function member of the same name is treated as describing an overload of the same function. Of note, too, is that in the case of interface A merging with later interface A (here called A&#39;), the overload set of A&#39; will have a higher precedence than that of interface A.
</p></div><div role="item"><p>比如在下面这个例子中：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">That is, in the example:
</p></div><pre><code class="lang-js">interface Document {
    createElement(tagName: any): Element;
}
interface Document {
    createElement(tagName: string): HTMLElement;
}
interface Document {
    createElement(tagName: &quot;div&quot;): HTMLDivElement;
    createElement(tagName: &quot;span&quot;): HTMLSpanElement;
    createElement(tagName: &quot;canvas&quot;): HTMLCanvasElement;
}
</code></pre>
<div role="item"><p>这两个接口将会合并创造出一个声明。注意每个接口中的元素将会维持同样的顺序，只是这些接口身合并时，后出现的重载集合会出现在前面：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The two interfaces will merge to create a single declaration. Notice that the elements of each group maintains the same order, just the groups themselves are merged with later overload sets coming first:
</p></div><pre><code class="lang-js">interface Document {
    createElement(tagName: &quot;div&quot;): HTMLDivElement;
    createElement(tagName: &quot;span&quot;): HTMLSpanElement;
    createElement(tagName: &quot;canvas&quot;): HTMLCanvasElement;
    createElement(tagName: string): HTMLElement;
    createElement(tagName: any): Element;
}
</code></pre>
<h2 class="section-title"><a name="合并模块" class="anchor" href="#合并模块"><span class="header-link"></span></a>合并模块</h2><div role="item"><p>和接口相似，拥有相同名称的模块也会合并它们的成员。由于模块会同时创建一个命名空间和一个值，这里我们需要同时理解这二者是如何合并的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Similarly to interfaces, modules of the same name will also merge their members. Since modules create both a namespace and a value, we need to understand how both merge.
</p></div><div role="item"><p>当合并两名命名空间时，每个模块输出的接口的声明中所创建的类型的定义会相互合并。它们会创建一个带有合并后的接口的命名空间。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To merge the namespaces, type definitions from exported interfaces declared in each module are themselves merged, forming a single namespace with merged interface definitions inside.
</p></div><div role="item"><p>当合并值时，两个模块中的值会合并在一起。如果两个模块中有同名称的值，则第二个模块中的值优先。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To merge the value, at each declaration site, if a module already exists with the given name, it is further extended by taking the existing module and adding the exported members of the second module to the first.
</p></div><div role="item"><p>下面这个例子中的&#39;Animals&#39;的声明合并：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The declaration merge of &#39;Animals&#39; in this example:
</p></div><pre><code class="lang-js">module Animals {
    export class Zebra { }
}

module Animals {
    export interface Legged { numberOfLegs: number; }
    export class Dog { }
}
</code></pre>
<div role="item"><p>等同于：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">is equivalent to:
</p></div><pre><code class="lang-js">module Animals {
    export interface Legged { numberOfLegs: number; }

    export class Zebra { }
    export class Dog { }
}
</code></pre>
<div role="item"><p>虽然这个模块合并的例子对我们的理解很有帮助，但我们同样也需要知道在未被输出的成员上到底发生了什么，来帮助我们更完整地理解模块合并。未被输出的成员只在原模块（未被合并的模块）中可见。这意味着来自不同声明中的成员即便在合并以后也不能看到对方未被输出的成员。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">This model of module merging is a helpful starting place, but to get a more complete picture we need to also understand what happens with non-exported members. Non-exported members are only visible in the original (un-merged) module. This means that after merging, merged members that came from other declarations can not see non-exported members.
</p></div><div role="item"><p>我们可以通过下面的例子更好地理解这一点：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">We can see this more clearly in this example:
</p></div><pre><code class="lang-js">module Animal {
    var haveMuscles = true;

    export function animalsHaveMuscles() {
        return haveMuscles;
    }
}

module Animal {
    export function doAnimalsHaveMuscles() {
        return haveMuscles;  // &lt;-- error, haveMuscles is not visible here
    }
}
</code></pre>
<div role="item"><p>因为haveMuscles并未被输出，所以只有在未合并前处在同一个模块中的animalsHaveMuscles函数才能知道haveMuscles的存在。虽然在被合并以后，doAnimalsHaveMuscles函数也是Animal模块的一部分，但它无法得知另一个模块中的那些未被输出的成员。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Because haveMuscles is not exported, only the animalsHaveMuscles function that shares the same un-merged module can see the symbol. The doAnimalsHaveMuscles function, even though it&#39;s part of the merged Animal module can not see this un-exported member.
</p></div><h2 class="section-title"><a name="用模块合并类，函数和枚举" class="anchor" href="#用模块合并类，函数和枚举"><span class="header-link"></span></a>用模块合并类，函数和枚举</h2><div role="item"><p>事实上模块非常灵活，它也可以合并其他类型的声明。想要合并其他类型的声明的话，这个模块的声明就必须要紧跟在它要合并的其他声明的后面。这样声明得到的结果，会同时拥有这两种声明类型的属性。TypeScript正是通过这一能力来模拟JavaScript和其他一些编程语言上的设计模式的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Modules are flexible enough to also merge with other types of declarations. To do so, the module declaration must follow the declaration it will merge with. The resulting declaration has properties of both declaration types. TypeScript uses this capability to model some of patterns in JavaScript as well as other programming languages.
</p></div><div role="item"><p>我们要看的第一个模块合并的例子是用来合并一个模块和一个类的。这让声明内部类成为了可能。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The first module merge we&#39;ll cover is merging a module with a class. This gives the user a way of describing inner classes.
</p></div><pre><code class="lang-js">class Album {
    label: Album.AlbumLabel;
}
module Album {
    export class AlbumLabel { }
}
</code></pre>
<div role="item"><p>这里合并后的成员的可见性同我们在&#39;Merging Modules&#39;部分中描述的是一样的。所以我们必须输出AlbumLabel类，来使被合并的类能够看见它。合并的结果便是是一个类出现在了另一个类中。你用样也可以用模块来给一个已经存在的类添加更多的静态成员。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The visibility rules for merged members is the same as described in the &#39;Merging Modules&#39; section, so we must export the AlbumLabel class for the merged class to see it. The end result is a class managed inside of another class. You can also use modules to add more static members to an existing class.
</p></div><div role="item"><p>除了内部类的模式以外，你可能也很熟悉下面这种JavaScript应用：先创建一个函数，然后再给这个函数添加其他的属性。通过TypeScript的声明合并，你可以在保障类型安全（type-safe）的情况下来实现这种定义。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In addition to the pattern of inner classes, you may also be familiar with JavaScript practice of creating a function and then extending the function further by adding properties onto the function. TypeScript uses declaration merging to build up definitions like this in a type-safe way.
</p></div><pre><code class="lang-js">function buildLabel(name: string): string {
    return buildLabel.prefix + name + buildLabel.suffix;
}

module buildLabel {
    export var suffix = &quot;&quot;;
    export var prefix = &quot;Hello, &quot;;
}

alert(buildLabel(&quot;Sam Smith&quot;));
</code></pre>
<div role="item"><p>相似地，模块也可以用静态成员来扩展枚举。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Similarly, modules can be used to extend enums with static members:
</p></div><pre><code class="lang-js">enum Color {
    red = 1,
    green = 2,
    blue = 4
}

module Color {
    export function mixColor(colorName: string) {
        if (colorName == &quot;yellow&quot;) {
            return Color.red + Color.green;
        }
        else if (colorName == &quot;white&quot;) {
            return Color.red + Color.green + Color.blue;
        }
        else if (colorName == &quot;magenta&quot;) {
            return Color.red + Color.blue;
        }
        else if (colorName == &quot;cyan&quot;) {
            return Color.green + Color.blue;
        }
    }
}
</code></pre>
<h2 class="section-title"><a name="不被允许的合并" class="anchor" href="#不被允许的合并"><span class="header-link"></span></a>不被允许的合并</h2><div role="item"><p>在TypeScript中，并不是所有类型都能够合并。到目前为止，一个类不能合并另一个类，变量与类之间不能够合并，接口和类之间也不能够合并。如果你想要模拟类的合并的话，你可以通过Mixins部分来了解更多。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Not all merges are allowed in TypeScript. Currently, classes can not merge with other classes, variables and classes can not merge, nor can interfaces and classes. For information on mimicking classes merging, see the Mixins in TypeScript section.
</p></div><hr>
<h1 class="section-title"><a name="类型推断" class="anchor" href="#类型推断"><span class="header-link"></span></a>类型推断</h1><div role="item"><p>在本节中，我们将讲到TypeScript中的类型推断（type inference）。我们将详细讲述类型推断发生的时机及发生的方式。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In this section, we will cover type inference in TypeScript. Namely, we&#39;ll discuss where and how types are inferred.
</p></div><h2 class="section-title"><a name="基础" class="anchor" href="#基础"><span class="header-link"></span></a>基础</h2><div role="item"><p>当没有关于类型的明确解释时，有几种情况会使得TypeScript使用类型推断来提供类型信息。举例来说，在下面的代码中：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In TypeScript, there are several places where type inference is used to provide type information when there is no explicit type annotation. For example, in this code
</p></div><pre><code class="lang-js">var x = 3;
</code></pre>
<div role="item"><p>变量x的类型会被推断为数字。这种类型推断会发生在下列情况中：初始化变量和成员，设置参数的默认值，在决定函数的返回类型时。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The type of the x variable is inferred to be number. This kind of inference takes place when initializing variables and members, setting parameter default values, and determining function return types.
</p></div><div role="item"><p>在大多数情况下，类型推断的结果很明了。我们将在后面探索类型推断中一些比较微妙的情况。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In most cases, type inference is straightforward. In the following sections, we&#39;ll explore some of the nuance in how types are inferred.
</p></div><h2 class="section-title"><a name="最佳通用类型" class="anchor" href="#最佳通用类型"><span class="header-link"></span></a>最佳通用类型</h2><div role="item"><p>当我们需要从多个表达式中推断类型时，我们会通过这些表达式计算出一个&quot;最佳通用类型&quot;（&quot;best common type&quot;）。举例来说，<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When a type inference is made from several expressions, the types of those expressions are used to calculate a &quot;best common type&quot;. For example,
</p></div><pre><code class="lang-js">var x = [0, 1, null];
</code></pre>
<div role="item"><p>在推断上面例子中x的类型时，我们必须要考虑到数组中每个元素的类型。这里我们有数字和null两种可能，而最佳通用类型算法会根据每种类型的情况，选择一种可以兼容所有其他选择的类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To infer the type of x in the example above, we must consider the type of each array element. Here we are given two choices for the type of the array: number and null. The best common type algorithm considers each candidate type, and picks the type that is compatible with all the other candidates.
</p></div><div role="item"><p>因为我们需要从候选类型中选择最佳通用类型，所以也可能出现没有一种类型可以兼容所有类型的情况。举例来说：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Because the best common type has to be chosen from the provided candidate types, there are some cases where types share a common structure, but no one type is the super type of all candidate types. For example:
</p></div><pre><code class="lang-js">var zoo = [new Rhino(), new Elephant(), new Snake()];
</code></pre>
<div role="item"><p>在理想的状况下，我们希望zoo 被推断为Animal[]。但是由于数组中并没有Animal类型，我们无法推断出这个数组元素的类型。为了应对这类情况，在数组中如果没有一个元素的类型是其他类型的超类型（super type）的话，我们需要明确提供这个数组的类型：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Ideally, we may want zoo to be inferred as an Animal[], but because there is no object that is strictly of type Animal in the array, we make no inference about the array element type. To correct this, instead explicitly provide the type when no one type is a super type of all other candidates:
</p></div><pre><code class="lang-js">var zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()];
</code></pre>
<div role="item"><p>当找不到最佳通用类型时，类型推断的结果就会变成空对象类型，即{}。因为这种类型并没有成员，所以尝试使用该类型上的任何属性都会产生错误。但在这种我们不能隐式推断出对象的类型的情况下，你仍旧能够通过不涉及类型的操作来安全地使用这个对象。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When no best common type is found, the resulting inference is the empty object type, {}. Because this type has no members, attempting to use any properties of it will cause an error. This result allows you to still use the object in a type-agnostic manner, while providing type safety in cases where the type of the object can&#39;t be implicitly determined.
</p></div><h2 class="section-title"><a name="上下文类型" class="anchor" href="#上下文类型"><span class="header-link"></span></a>上下文类型</h2><div role="item"><p>类型推断也能作用于TypeScript中的一些其他情况，其中一种情况便是&quot;上下文类型&quot;（&quot;contextual typing&quot;）。上下文类型作用在“一个表达式的类型可以通过它出现的位置被推断出”的情况下。举例来说：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Type inference also works in &quot;the other direction&quot; in some cases in TypeScript. This is known as &quot;contextual typing&quot;. Contextual typing occurs when the type of an expression is implied by its location. For example:
</p></div><pre><code class="lang-js">window.onmousedown = function(mouseEvent) {
    console.log(mouseEvent.buton);  //&lt;- Error
};
</code></pre>
<div role="item"><p>上面的代码会抛出类型错误。因为TypeScript的类型检查器会用Window.onmousedown函数的类型来推断赋值符号另一侧的函数表达式的类型。在这种情况下，它就能推断出mouseEvent参数的类型。如果函数表达式不在这个关乎上下文类型的位置上的话，mouseEvent参数就可以是any类型，而且不会有错误抛出。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">For the code above to give the type error, the TypeScript type checker used the type of the Window.onmousedown function to infer the type of the function expression on the right hand side of the assignment. When it did so, it was able to infer the type of the mouseEvent parameter. If this function expression were not in a contextually typed position, the mouseEvent parameter would have type any, and no error would have been issued.
</p></div><div role="item"><p>如果我们明确地指定了这个表达式的类型的话，上下文类型就会被忽略。我们可以这样来写上面的例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">If the contextually typed expression contains explicit type information, the contextual type is ignored. Had we written the above example:
</p></div><pre><code class="lang-js">window.onmousedown = function(mouseEvent: any) {
    console.log(mouseEvent.buton);  //&lt;- Now, no error is given
};
</code></pre>
<div role="item"><p>带有明确类型注释的函数表达式的参数可以覆盖上下文类型。这样就不会有上下文类型其作用，也就不会有错误产生了。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The function expression with an explicit type annotation on the parameter will override the contextual type. Once it does so, no error is given as no contextual type applies.
</p></div><div role="item"><p>上下文类型可以作用在很多场景中。常见的例子包括：函数调用中的参数，赋值时等号的右边部分，类型判断，对象的成员，迭代数组，以及返回声明（return statements）。上下文类型也会成为最佳通用类型的一个候选类型。举例来说：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Contextual typing applies in many cases. Common cases include arguments to function calls, right hand sides of assignments, type assertions, members of object and array literals, and return statements. The contextual type also acts as a candidate type in best common type. For example:
</p></div><pre><code class="lang-js">function createZoo(): Animal[] {
    return [new Rhino(), new Elephant(), new Snake()];
}
</code></pre>
<div role="item"><p>在这个例子中，我们有四个最佳候选类型：Animal, Rhino, Elephant, and Snake。在这里最佳通用类型算法当然会选择Animal。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In this example, best common type has a set of four candidates: Animal, Rhino, Elephant, and Snake. Of these, Animal can be chosen by the best common type algorithm.
</p></div><hr>
<h1 class="section-title"><a name="类型兼容性" class="anchor" href="#类型兼容性"><span class="header-link"></span></a>类型兼容性</h1><div role="item"><p>TypeScript中的类型之间是否兼容，取决于其结构性子类型（structural subtyping）。结构性子类型是仅根据类型的成员来判断类型之间是否兼容，它和名义类型（nominal typing）形成了鲜明的对比。让我们来看看下面的代码：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Type compatibility in TypeScript is based on structural subtyping. Structural typing is a way of relating types based solely on their members. This is in contrast with nominal typing. Consider the following code:
</p></div><pre><code class="lang-js">interface Named {
    name: string;
}

class Person {
    name: string;
}

var p: Named;
// OK, because of structural typing
p = new Person();
</code></pre>
<div role="item"><p>因为Person类并没有把它自己明确地描述为Named接口的实现，所以在像C#和Java这样的名义型类型的语言中，等价的代码会抛出错误。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In nominally-typed languages like C# or Java, the equivalent code would be an error because the Person class does not explicitly describe itself as being an implementor of the Named interface.
</p></div><div role="item"><p>TypeScript的结构性类型系统（structural type system）是依据JavaScript代码的典型写法设计而来的。因为JavaScript中会广泛使用函数表达式和对象字面量，所以用结构性类型系统代替名义性的结构系统来表达JavaScript代码之间关系会显得更加自然。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">TypeScript’s structural type system was designed based on how JavaScript code is typically written. Because JavaScript widely uses anonymous objects like function expressions and object literals, it’s much more natural to represent the kinds of relationships found in JavaScript libraries with a structural type system instead of a nominal one.
</p></div><h2 class="section-title"><a name="关于可靠性" class="anchor" href="#关于可靠性"><span class="header-link"></span></a>关于可靠性</h2><div role="item"><p>TypeScript中的类型系统允许一些特定的操作，这些操作虽然在编译阶段是不可预测的，但TypeScript却可以保证它们的安全性。当类型系统有这样的属性时，我们就说它是&quot;不可靠&quot;的。TypeScript所允许的这些不可靠的行为都是经过仔细考虑的。通过这个文档，我们将阐述这些行为会在何时产生，以及这些行为产生背后的情景与动机。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">TypeScript’s type system allows certain operations that can’t be known at compile-time to be safe. When a type system has this property, it is said to not be “sound”. The places where TypeScript allows unsound behavior were carefully considered, and throughout this document we’ll explain where these happen and the motivating scenarios behind them.
</p></div><h2 class="section-title"><a name="起步" class="anchor" href="#起步"><span class="header-link"></span></a>起步</h2><div role="item"><p>TypeScript的结构性类型系统的一个基本原则是：如果y拥有x上的所有成员，我们就说x与y是兼容的。举例来说：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The basic rule for TypeScript’s structural type system is that x is compatible with y if y has at least the same members as x. For example:
</p></div><pre><code class="lang-js">interface Named {
    name: string;
}

var x: Named;
// y’s inferred type is { name: string; location: string; }
var y = { name: &#39;Alice&#39;, location: &#39;Seattle&#39; };
x = y;
</code></pre>
<div role="item"><p>当编译器在检查y能否赋值给x时，它会检查x上的每个属性是否都能在y上被找到对应的，兼容的属性。在这个例子中，y必须有一个名为‘name’的string属性，我们才能说它和x兼容。因为这里y确实有，所以这个赋值是被允许的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To check whether y can be assigned to x, the compiler checks each property of x to find a corresponding compatible property in y. In this case, y must have a member called ‘name’ that is a string. It does, so the assignment is allowed.
</p></div><div role="item"><p>在检查用来调用函数的参数时，这个规则也同样适用：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The same rule for assignment is used when checking function call arguments:
</p></div><pre><code class="lang-js">function greet(n: Named) {
    alert(&#39;Hello, &#39; + n.name);
}
greet(y); // OK
</code></pre>
<div role="item"><p>记住虽然‘y’有一个额外的‘location’属性，但这里并不会产生错误。只有目标类型（这个例子中为‘Named’）的成员会被用来检查它们之间的兼容性。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Note that ‘y’ has an extra ‘location’ property, but this does not create an error. Only members of the target type (‘Named’ in this case) are considered when checking for compatibility.
</p></div><div role="item"><p>这个比较的过程会递归地进行，以遍历这个类型的每一个成员及其子成员。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">This comparison process proceeds recursively, exploring the type of each member and sub-member.
</p></div><h2 class="section-title"><a name="比较两个函数" class="anchor" href="#比较两个函数"><span class="header-link"></span></a>比较两个函数</h2><div role="item"><p>当我们在比较原生的类型（primitive types）和对象类型（object types）时，整个过程会直接了当。让我们从两个只有参数列表不同的函数这个基本的例子说起：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">While comparing primitive types and object types is relatively straightforward, the question of what kinds of functions should be considered compatible. Let’s start with a basic example of two functions that differ only in their argument lists:
</p></div><pre><code class="lang-js">var x = (a: number) =&gt; 0;
var y = (b: number, s: string) =&gt; 0;

y = x; // OK
x = y; // Error
</code></pre>
<div role="item"><p>当检查x能否赋值给y时，我们首先会检查它们的参数列表。对于y中的每个参数，我们必须能在x中也找到对应的，兼容类型的参数，我们才能说它没有问题。注意参数的名称并不在考虑范围之内，我们只关注它们的类型。在这个例子中，x中的每个参数都能对应y上的参数，所以这个赋值是被允许的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">To check if x is assignable to y, we first look at the parameter list. Each parameter in y must have a corresponding parameter in x with a compatible type. Note that the names of the parameters are not considered, only their types. In this case, every parameter of x has a corresponding compatible parameter in y, so the assignment is allowed.
</p></div><div role="item"><p>而第二个赋值就会产生一个错误。因为y需要的第二个参数‘x’并没有，所以这个赋值是不被允许的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The second assignment is an error, because y has a required second parameter that ‘x’ does not have, so the assignment is disallowed.
</p></div><div role="item"><p>你可能会好奇为什么我们会允许像上面y = x这样&#39;丢弃&#39;参数。实际上在在JavaScript中，忽略额外的函数参数的情况非常普遍。比如Array#forEach会提供三个参数给回调函数：数组元素，它的索引（index）以及包含这个元素的数组。所以允许提供一个只使用第一个参数的回调函数是很有用的：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">You may be wondering why we allow ‘discarding’ parameters like in the example y = x. The reason is that assignment is allowed is that ignoring extra function parameters is actually quite common in JavaScript. For example, Array#forEach provides three arguments to the callback function: the array element, its index, and the containing array. Nevertheless, it’s very useful to provide a callback that only uses the first argument:
</p></div><pre><code class="lang-js">var items = [1, 2, 3];

// Don&#39;t force these extra arguments
items.forEach((item, index, array) =&gt; console.log(item));

// Should be OK!
items.forEach((item) =&gt; console.log(item));
</code></pre>
<div role="item"><p>现在再让我们看看函数的返回类型是如何被处理的。让我们使用两个只有返回类型不一样的函数：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Now let’s look at how return types are treated, using two functions that differ only by their return type:
</p></div><pre><code class="lang-js">var x = () =&gt; ({name: &#39;Alice&#39;});
var y = () =&gt; ({name: &#39;Alice&#39;, location: &#39;Seattle&#39;});

x = y; // OK
y = x; // Error because x() lacks a location property
</code></pre>
<div role="item"><p>类型系统会强制要求原函数的返回类型是目标函数的返回类型的子类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The type system enforces that the source function’s return type be a subtype of the target type’s return type.
</p></div><h3 class="section-title"><a name="函数参数双向协变（Bivariance）" class="anchor" href="#函数参数双向协变（Bivariance）"><span class="header-link"></span></a>函数参数双向协变（Bivariance）</h3><div role="item"><p>当我们在比较函数参数的类型时，如果原来的参数可以赋值给目标参数的话，那么赋值就会成功。反之则会失败。由于我们在最终调用函数时，可能调用的是某个只需要特定类型参数的函数，而却给它传入了类型更宽泛的参数，所以这种做法理论上并不安全。但实际上这种类型的错误是很少见的，并且允许这种做法能允许我们使用更多在JavaScript上通用的模式。下面是一个简短的例子：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When comparing the types of function parameters, assignment succeeds if either the source parameter is assignable to the target parameter, or vice versa. This is unsound because a caller might end up being given a function that takes a more specialized type, but invokes the function with a less specialized type. In practice, this sort of error is rare, and allowing this enables many common JavaScript patterns. A brief example:
</p></div><pre><code class="lang-js">enum EventType { Mouse, Keyboard }

interface Event { timestamp: number; }
interface MouseEvent extends Event { x: number; y: number }
interface KeyEvent extends Event { keyCode: number }

function listenEvent(eventType: EventType, handler: (n: Event) =&gt; void) {
    /* ... */
}

// Unsound, but useful and common
listenEvent(EventType.Mouse, (e: MouseEvent) =&gt; console.log(e.x + &#39;,&#39; + e.y));

// Undesirable alternatives in presence of soundness
listenEvent(EventType.Mouse, (e: Event) =&gt; console.log((&lt;MouseEvent&gt;e).x + &#39;,&#39; + (&lt;MouseEvent&gt;e).y));
listenEvent(EventType.Mouse, &lt;(e: Event) =&gt; void&gt;((e: MouseEvent) =&gt; console.log(e.x + &#39;,&#39; + e.y)));

// Still disallowed (clear error). Type safety enforced for wholly incompatible types
listenEvent(EventType.Mouse, (e: number) =&gt; console.log(e));
</code></pre>
<h3 class="section-title"><a name="可选参数和剩余参数" class="anchor" href="#可选参数和剩余参数"><span class="header-link"></span></a>可选参数和剩余参数</h3><div role="item"><p>当我们在比较函数之间的兼容性时，可选参数与必选参数之间是可以互换的。源类型（source type）上额外的可选参数不会产生错误，目标类型（target type）上的可选参数即便没有对应的参数传入也不会产生错误。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When comparing functions for compatibility, optional and required parameters are interchangeable. Extra optional parameters of the source type are not an error, and optional parameters of the target type without corresponding parameters in the target type are not an error.
</p></div><div role="item"><p>如果一个函数有剩余参数的话，剩余参数就会被当成是无数个可选参数。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When a function has a rest parameter, it is treated as if it were an infinite series of optional parameters.
</p></div><div role="item"><p>虽然这种做法从类型系统的角度上来看是不可靠的，但是从运行的角度来说，可选参数做法并不是那么容易实现的。因为对于大多数函数而言，在可选参数的位置上传入个‘undefined’也是等价的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">This is unsound from a type system perspective, but from a runtime point of view the idea of an optional parameter is generally not well-enforced since passing ‘undefined’ in that position is equivalent for most functions.
</p></div><div role="item"><p>使用函数的常见的模式之一是：传入一个回调函数并执行它。在这一过程中，调用函数参数的数量对于开发人员来说是可以预见的，但类型系统却无从得知参数数量。下面这个例子正体现了这一点：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The motivating example is the common pattern of a function that takes a callback and invokes it with some predictable (to the programmer) but unknown (to the type system) number of arguments:
</p></div><pre><code class="lang-js">function invokeLater(args: any[], callback: (...args: any[]) =&gt; void) {
    /* ... Invoke callback with &#39;args&#39; ... */
}

// Unsound - invokeLater &quot;might&quot; provide any number of arguments
invokeLater([1, 2], (x, y) =&gt; console.log(x + &#39;, &#39; + y));

// Confusing (x and y are actually required) and undiscoverable
invokeLater([1, 2], (x?, y?) =&gt; console.log(x + &#39;, &#39; + y));
</code></pre>
<h3 class="section-title"><a name="函数与重载" class="anchor" href="#函数与重载"><span class="header-link"></span></a>函数与重载</h3><div role="item"><p>对于有重载的函数来说，源类型上的每个重载都需要在目标类型上有一个可兼容的签名（signature）。这可以确保我们在任意状况下都能够像调用源函数一样调用目标函数。在检查兼容性时，函数上特定的重载签名（使用字面量的重载）并不参与检查。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When a function has overloads, each overload in the source type must be matched by a compatible signature on the target type. This ensures that the target function can be called in all the same situations as the source function. Functions with specialized overload signatures (those that use string literals in their overloads) do not use their specialized signatures when checking for compatibility.
</p></div><h2 class="section-title"><a name="枚举" class="anchor" href="#枚举"><span class="header-link"></span></a>枚举</h2><div role="item"><p>枚举和数字之间是相互兼容的，不同枚举类型的枚举值之间是不兼容的。举例来说：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Enums are compatible with numbers, and numbers are compatible with enums. Enum values from different enum types are considered incompatible. For example,
</p></div><pre><code class="lang-js">enum Status { Ready, Waiting };
enum Color { Red, Blue, Green };

var status = Status.Ready;
status = Color.Green;  //error
</code></pre>
<h2 class="section-title"><a name="类" class="anchor" href="#类"><span class="header-link"></span></a>类</h2><div role="item"><p>类和对象字面量类型及接口相似，但它们同时拥有静态部分和实例部分。当我们在比较同一个类下的两个对象之间兼容性时，我们只比较实例上的成员。静态成员和构造函数不会影响它们的兼容性。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Classes work similarly to object literal types and interfaces with one exception: they have both a static and an instance type. When comparing two objects of a class type, only members of the instance are compared. Static members and constructors do not affect compatibility. 
</p></div><pre><code class="lang-js">class Animal {
    feet: number;
    constructor(name: string, numFeet: number) { }
}

class Size {
    feet: number;
    constructor(numFeet: number) { }
}

var a: Animal;
var s: Size;

a = s;  //OK
s = a;  //OK
</code></pre>
<h3 class="section-title"><a name="类中的私有成员" class="anchor" href="#类中的私有成员"><span class="header-link"></span></a>类中的私有成员</h3><div role="item"><p>类中的私有成员会影响它们的兼容性。当我们在检查类实例的兼容性时，如果这个实例包含一个私有成员，那么只有在目标类型上也包含一个来源于同一个类的同一个私有成员，我们才认为它们是兼容的。这意味这一个类和它的超类是兼容的，但和另一个与它结构相同而继承结构不同的类是不兼容的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Private members in a class affect their compatibility. When an instance of a class is checked for compatibility, if it contains a private member, the target type must also contain a private member that originated from the same class. This allows, for example, a class to be assignment compatible with its super class but not with classes from a different inheritance hierarchy which otherwise have the same shape.
</p></div><h2 class="section-title"><a name="泛型" class="anchor" href="#泛型"><span class="header-link"></span></a>泛型</h2><div role="item"><p>由于TypeScript是结构性类型系统，所以当类型参数被用作成员类型的一部分时，它只对使用了类型参数的成员产生影响。举例来说：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Because TypeScript is a structural type system, type parameters only affect the resulting type when consumed as part of the type of a member. For example,
</p></div><pre><code class="lang-js">interface Empty&lt;T&gt; {
}
var x: Empty&lt;number&gt;;
var y: Empty&lt;string&gt;;

x = y;  // okay, y matches structure of x
</code></pre>
<div role="item"><p>在上面的例子中，由于x和y的结构中并没有使用类型参数，所以它们是兼容的。现在让我们给Empty<T>添加一个成员看看结果如何：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In the above, x and y are compatible because their structures do not use the type argument in a differentiating way. Changing this example by adding a member to Empty<T> shows how this works:
</p></div><pre><code class="lang-js">interface NotEmpty&lt;T&gt; {
    data: T;
}
var x: NotEmpty&lt;number&gt;;
var y: NotEmpty&lt;string&gt;;

x = y;  // error, x and y are not compatible
</code></pre>
<div role="item"><p>在这种情况下，使用了类型参数，并使其生效的泛型类型和非泛型类型没有什么不同。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In this way, a generic type that has its type arguments specified acts just like a non-generic type.
</p></div><div role="item"><p>对于没有使用指定的类型参数的泛型类型来说，所有未指定类型的参数都会被当作&#39;any&#39;类型来进行兼容性检查。检查方式和非泛型类型是一样的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">For generic types that do not have their type arguments specified, compatibility is checked by specifying &#39;any&#39; in place of all unspecified type arguments. The resulting types are then checked for compatibility, just as in the non-generic case.
</p></div><div role="item"><p>举例来说：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">For example,
</p></div><pre><code class="lang-js">var identity = function&lt;T&gt;(x: T): T { 
    // ...
}

var reverse = function&lt;U&gt;(y: U): U {
    // ...
}

identity = reverse;  // Okay because (x: any)=&gt;any matches (y: any)=&gt;any
</code></pre>
<h2 class="section-title"><a name="进阶话题" class="anchor" href="#进阶话题"><span class="header-link"></span></a>进阶话题</h2><h3 class="section-title"><a name="子类型 vs 赋值" class="anchor" href="#子类型 vs 赋值"><span class="header-link"></span></a>子类型 vs 赋值</h3><div role="item"><p>我们一直在使用&#39;兼容&#39;（compatible）这个词，但它本身并不是这门语言规定中的细则。实际上TypeScript中有两种类型的兼容：子类型上的和赋值上的。它们之间的不同只在于，赋值时会有额外的子类型兼容性。它会允许把&#39;any&#39;或枚举类型赋值为其他类型，或把&#39;any&#39;或枚举类型赋值给其他类型，其中枚举类型的数值必须对应。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">So far, we&#39;ve used &#39;compatible&#39;, which is not a term defined in the language spec. In TypeScript, there are two kinds of compatibility: subtype and assignment. These differ only in that assignment extends subtype compatibility with rules to allow assignment to and from &#39;any&#39; and to and from enum with corresponding numeric values. 
</p></div><div role="item"><p>TypeScript会根据场景的不同使用两种兼容机制。从实际角度出发，类型兼容性会由赋值兼容性来决定，甚至是在implements和extends子句上。你可以查阅TypeScript上的细则以获取更多信息。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Different places in the language use one of the two compatibility mechanisms, depending on the situation. For practical purposes, type compatibility is dictated by assignment compatibility even in the cases of the implements and extends clauses. For more information, see the TypeScript spec.
</p></div><hr>
<h1 class="section-title"><a name="编写.d.ts文件" class="anchor" href="#编写.d.ts文件"><span class="header-link"></span></a>编写.d.ts文件</h1><div role="item"><p>当我们要使用一个外部JavaScript库或是新的API时，我们需要用一个声明文件（.d.ts）来描述这个库的结构。本节会讲述写这种定义文件（definition files）时会涉及到的一些高级概念。之后会用一些例子，来展示这些概念所对应的定义文件描述。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When using an external JavaScript library, or new host API, you&#39;ll need to use a declaration file (.d.ts) to describe the shape of that library. This guide covers a few high-level concepts specific to writing definition files, then proceeds with a number of examples that show how to transcribe various concepts to their matching definition file descriptions.
</p></div><h2 class="section-title"><a name="指导与细则" class="anchor" href="#指导与细则"><span class="header-link"></span></a>指导与细则</h2><h3 class="section-title"><a name="工作流" class="anchor" href="#工作流"><span class="header-link"></span></a>工作流</h3><div role="item"><p>写.d.ts文件最好的方式不是根据代码来写，而是根据文档来写。根据文档来写代码能够保证你要表达的东西不会被实现细节所影响。而且文档通常也比JS代码要容易理解。所以我们后面的例子都会假设你正在读一个解释表达代码例子的文档的情景来写。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The best way to write a .d.ts file is to start from the documentation of the library, not the code. Working from the documentation ensures the surface you present isn&#39;t muddied with implementation details, and is typically much easier to read than JS code. The examples below will be written as if you were reading documentation that presented example calling code.
</p></div><h3 class="section-title"><a name="命名空间" class="anchor" href="#命名空间"><span class="header-link"></span></a>命名空间</h3><div role="item"><p>当你在定义接口时（比如说&quot;options&quot;对象），你可以决定是否要把这些类型放到一个模块中。你需要根据具体情况来做这个决定 -- 如果用户很可能时常需要声明这个类型的变量或参数，并且需要它的命名不与其他类型冲突的话，那你大可把它放到一个全局命名空间中。如果这个类型很可能不需要被直接引用，或是不太适合以一个独特的名字来命名的话，那你应该把它放在模块内以避免与其他类型发生冲突。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When defining interfaces (for example, &quot;options&quot; objects), you have a choice about whether to put these types inside a module or not. This is largely a judgement call -- if the consumer is likely to often declare variables or parameters of that type, and the type can be named without risk of colliding with other types, prefer placing it in the global namespace. If the type is not likely to be referenced directly, or can&#39;t be named with a reasonably unique name, do use a module to prevent it from colliding with other types.
</p></div><h3 class="section-title"><a name="回调" class="anchor" href="#回调"><span class="header-link"></span></a>回调</h3><div role="item"><p>很多JavaScript的库会事先把一个函数作为参数，并在之后用获取到的参数来调用它。当我们在写这种类型的函数签名（function signatures）时，我们不应该把它们当作是可选参数。我们需要认真考虑&quot;我们需要传入什么参数&quot;而不是&quot;我们要用什么参数&quot;。虽然TypeScript 从0.9.7版本开始不再限制我们传入函数作为可选参数，我们仍旧可以通过外部工具在参数的可选性上强制进行双向协变（bivariance）。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Many JavaScript libraries take a function as a parameter, then invoke that function later with a known set of arguments. When writing the function signatures for these types, do not mark those parameters as optional. The right way to think of this is &quot;What parameters will be provided?&quot;, not &quot;What parameters will be consumed?&quot;. While TypeScript 0.9.7 and above does not enforce that the optionality, bivariance on argument optionality might be enforced by an external linter.
</p></div><h3 class="section-title"><a name="扩展性和声明合并" class="anchor" href="#扩展性和声明合并"><span class="header-link"></span></a>扩展性和声明合并</h3><div role="item"><p>当我们在写定义文件时，我们需要格外注意TypeScript在扩展已有对象时的规则。你可以用匿名类型或接口来声明一个变量：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When writing definition files, it&#39;s important to remember TypeScript&#39;s rules for extending existing objects. You might have a choice of declaring a variable using an anonymous type or an interface type:
</p></div><p><strong>匿名类型变量</strong></p>
<pre><code class="lang-js">declare var MyPoint: { x: number; y: number; };
</code></pre>
<p><strong>接口类型变量</strong></p>
<pre><code class="lang-js">interface SomePoint { x: number; y: number; }
declare var MyPoint: SomePoint;
</code></pre>
<div role="item"><p>从使用者的角度来说，这两中声明是等价的。但我们可以通过接口合并来扩展SomePoint类型：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">From a consumption side these declarations are identical, but the type SomePoint can be extended through interface merging:
</p></div><pre><code class="lang-js">interface SomePoint { z: number; }
MyPoint.z = 4; // OK
</code></pre>
<div role="item"><p>你需要根据实际情况来决定是否允许你的声明通过这种方式被扩展。从这里也可以展示出你对这个库的想法。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Whether or not you want your declarations to be extensible in this way is a bit of a judgement call. As always, try to represent the intent of the library here.
</p></div><h3 class="section-title"><a name="解构类" class="anchor" href="#解构类"><span class="header-link"></span></a>解构类</h3><div role="item"><p>TypeScript中的类会创建出两种独立的类型：一种是实例类型，它定义了类实例上的成员；另一种是构造函数类型，它定义了构造函数的成员。因为构造函数类型包括了类中的静态成员，我们可以把当作是&quot;静态的&quot;类型。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Classes in TypeScript create two separate types: the instance type, which defines what members an instance of a class has, and the constructor function type, which defines what members the class constructor function has. The constructor function type is also known as the &quot;static side&quot; type because it includes static members of the class.
</p></div><div role="item"><p>虽然我们可以使用typeof关键字来引用一个类中的静态部分，但在写定义文件时，我们有时候需要用被解构过的类。它能明确地将类中的实例部分和静态部分分开。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">While you can reference the static side of a class using the typeof keyword, it is sometimes useful or necessary when writing definition files to use the decomposed class pattern which explicitly separates the instance and static types of class.
</p></div><div role="item"><p>举个例子，从一个使用者的角度来看，下面的两种声明方式几乎是等价的：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">As an example, the following two declarations are nearly equivalent from a consumption perspective:
</p></div><p><strong>标准声明方式</strong></p>
<pre><code class="lang-js">class A {
    static st: string;
    inst: number;
    constructor(m: any) {}
}
</code></pre>
<p><strong>解构方式</strong></p>
<pre><code class="lang-js">interface A_Static {
    new(m: any): A_Instance;
    st: string;
}
interface A_Instance {
    inst: number;
}
declare var A: A_Static;
</code></pre>
<div role="item"><p>它们的不同之处在于：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The trade-offs here are as follows:
</p></div><div role="item"><p>我们可以用extends继承标准的类，但不能继承解构过的类。除非下一个版本的TypeScript允许这种继承表达式。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Standard classes can be inherited from using extends; decomposed classes cannot. This might change in later version of TypeScript if arbitrary extends expressions are allowed.
</p></div><div role="item"><p>我们可以（通过声明合并）给标准的类和解构类上的静态部分添加成员。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">It is possible to add members later (through declaration merging) to the static side of both standard and decomposed classes.
</p></div><div role="item"><p>我们可以给解构过的类添加新的实例成员，但不能给标准类添加。在写解构类的时候，如果你想要添加更多类型的话，你可能需要想一些更有意义的名字。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">It is possible to add instance members to decomposed classes, but not standard classes
You&#39;ll need to come up with sensible names for more types when writing a decomposed class
</p></div><h3 class="section-title"><a name="命名习惯" class="anchor" href="#命名习惯"><span class="header-link"></span></a>命名习惯</h3><div role="item"><p>总的来说，不要在接口前加I（比如：IColor）。因为TypeScript中接口的概念要比C#或Java更宽泛。IFoo这类命名习惯没有太多作用。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In general, do not prefix interfaces with I (e.g. IColor). Because the concept of an interface in TypeScript is much more broad than in C# or Java, the IFoo naming convention is not broadly useful.
</p></div><h2 class="section-title"><a name="例子" class="anchor" href="#例子"><span class="header-link"></span></a>例子</h2><div role="item"><p>来看看下面的这些例子。每个例子都先给出了一个库的使用方式，然后再给出对于这样的库来说比较合适的类型定义。如果一个库有多种比较合适的定义方式的话，这里会把它们都列举出来。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Let&#39;s jump in to the examples section. For each example, sample usage of the library is provided, followed by the definition code that accurately types the usage. When there are multiple good representations, more than one definition sample might be listed.
</p></div><h3 class="section-title"><a name="Options对象" class="anchor" href="#Options对象"><span class="header-link"></span></a>Options对象</h3><p><strong>用法</strong></p>
<pre><code class="lang-js">animalFactory.create(&quot;dog&quot;);
animalFactory.create(&quot;giraffe&quot;, { name: &quot;ronald&quot; });
animalFactory.create(&quot;panda&quot;, { name: &quot;bob&quot;, height: 400 });
// Invalid: name must be provided if options is given
animalFactory.create(&quot;cat&quot;, { height: 32 });
</code></pre>
<p><strong>类型声明</strong></p>
<pre><code class="lang-js">module animalFactory {
    interface AnimalOptions {
        name: string;
        height?: number;
        weight?: number;
    }
    function create(name: string, animalOptions?: AnimalOptions): Animal;
}
</code></pre>
<h3 class="section-title"><a name="带有属性的函数" class="anchor" href="#带有属性的函数"><span class="header-link"></span></a>带有属性的函数</h3><p><strong>用法</strong></p>
<pre><code class="lang-js">zooKeeper.workSchedule = &quot;morning&quot;;
zooKeeper(giraffeCage);
</code></pre>
<p><strong>类型声明</strong></p>
<pre><code class="lang-js">// Note: Function must precede module
function zooKeeper(cage: AnimalCage);
module zooKeeper {
    var workSchedule: string;
}
</code></pre>
<h3 class="section-title"><a name="用new调用的函数" class="anchor" href="#用new调用的函数"><span class="header-link"></span></a>用new调用的函数</h3><p><strong>用法</strong></p>
<pre><code class="lang-js">var w = widget(32, 16);
var y = new widget(&quot;sprocket&quot;);
// w and y are both widgets
w.sprock();
y.sprock();
</code></pre>
<p><strong>类型声明</strong></p>
<pre><code class="lang-js">interface Widget {
    sprock(): void;
}

interface WidgetFactory {
    new(name: string): Widget;
    (width: number, height: number): Widget;
}

declare var widget: WidgetFactory;
</code></pre>
<h3 class="section-title"><a name="全局/对外部不可知的（external-agnostic）函数库" class="anchor" href="#全局/对外部不可知的（external-agnostic）函数库"><span class="header-link"></span></a>全局/对外部不可知的（external-agnostic）函数库</h3><p><strong>用法</strong></p>
<pre><code class="lang-js">// Either
import x = require(&#39;zoo&#39;);
x.open();
// or
zoo.open();
</code></pre>
<p><strong>类型声明</strong></p>
<pre><code class="lang-js">module zoo {
  function open(): void;
}

declare module &quot;zoo&quot; {
    export = zoo;
}
</code></pre>
<h3 class="section-title"><a name="外部模块中的单个复杂的对象" class="anchor" href="#外部模块中的单个复杂的对象"><span class="header-link"></span></a>外部模块中的单个复杂的对象</h3><p><strong>用法</strong></p>
<pre><code class="lang-js">// Super-chainable library for eagles
import eagle = require(&#39;./eagle&#39;);
// Call directly
eagle(&#39;bald&#39;).fly();
// Invoke with new
var eddie = new eagle(1000);
// Set properties
eagle.favorite = &#39;golden&#39;;
</code></pre>
<p><strong>类型声明</strong></p>
<pre><code class="lang-js">// Note: can use any name here, but has to be the same throughout this file
declare function eagle(name: string): eagle;
declare module eagle {
    var favorite: string;
    function fly(): void;
}
interface eagle {
    new(awesomeness: number): eagle;
}

export = eagle;
</code></pre>
<h3 class="section-title"><a name="回调" class="anchor" href="#回调"><span class="header-link"></span></a>回调</h3><p><strong>用法</strong></p>
<pre><code class="lang-js">addLater(3, 4, (x) =&gt; console.log(&#39;x = &#39; + x));
</code></pre>
<p><strong>类型声明</strong></p>
<pre><code class="lang-js">// Note: &#39;void&#39; return type is preferred here
function addLater(x: number, y: number, (sum: number) =&gt; void): void;
</code></pre>
<hr>
<h1 class="section-title"><a name="TypeScript 1.5" class="anchor" href="#TypeScript 1.5"><span class="header-link"></span></a>TypeScript 1.5</h1><h2 class="section-title"><a name="ES6模块" class="anchor" href="#ES6模块"><span class="header-link"></span></a>ES6模块</h2><div role="item"><p>TypeScript 1.5支持ECMAScript 6 （ES6）模块（modules）。你可以把ES6模块当作是带着新语法的TypeScript外部模块（external modules）：ES6的模块是被零散载入的源码文件，它们可以输入（import）其他的模块，也可以输出内容供外部使用（exports）。ES6模块给import和export声明提供了一些新的特性。虽然TypeScript并不强制要求在项目使用ES6模块，但我们还是推荐你在库和应用上使用这种新的模块语法，并更新原来的模块。ES6模块的和TypeScript原来的内部模块和外部模块是可以共存的。你甚至可以按你的意愿来构造并混合它们。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">TypeScript 1.5 supports ECMAScript 6 (ES6) modules. ES6 modules are effectively TypeScript external modules with a new syntax: ES6 modules are separately loaded source files that possibly import other modules and provide a number of externally accessible exports. ES6 modules feature several new export and import declarations. It is recommended that TypeScript libraries and applications be updated to use the new syntax, but this is not a requirement. The new ES6 module syntax coexists with TypeScript&#39;s original internal and external module constructs and the constructs can be mixed and matched at will.
</p></div><p><strong>Export声明</strong></p>
<div role="item"><p>除了TypeScript现有的export装饰声明（decorating declarations）外，我们也可以零散地用export声明来输出模块中的成员。我们甚至可以用子句（clauses）来给export中的内容替换名称。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In addition to the existing TypeScript support for decorating declarations with export, module members can also be exported using separate export declarations, optionally specifying different names for exports using as clauses.
</p></div><pre><code class="lang-js">interface Stream { ... }
function writeToStream(stream: Stream, data: string) { ... }
export { Stream, writeToStream as write };  // writeToStream exported as write
</code></pre>
<div role="item"><p>import声明也可以使用子句来给import后面的内容指定用于本地的名称。举例来说：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Import declarations, as well, can optionally use as clauses to specify different local names for the imports. For example:
</p></div><pre><code class="lang-js">import { read, write, standardOutput as stdout } from &quot;./inout&quot;;
var s = read(stdout);
write(stdout, s);
</code></pre>
<div role="item"><p>除了独立的import外，我们也可以通过导入命名空间来导入一整个模块：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">As an alternative to individual imports, a namespace import can be used to import an entire module:
</p></div><pre><code class="lang-js">import * as io from &quot;./inout&quot;;
var s = io.read(io.standardOutput);
io.write(io.standardOutput, s);
Re-exporting
</code></pre>
<div role="item"><p>通过使用from子句，一个模块可以复制给定的模块所输出的内容到当前模块中，而不需要生成用于本地的名称。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Using from clause a module can copy the exports of a given module to the current module without introducing local names.
</p></div><pre><code class="lang-js">export { read, write, standardOutput as stdout } from &quot;./inout&quot;;
</code></pre>
<div role="item"><p>export * 常被用在将一个模块的输出再次进行输出。在创建专门用来聚集其他模块输出的模块时，这种方式非常有用。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">export * can be used to re-export all exports of another module. This is useful for creating modules that aggregate the exports of several other modules.
</p></div><pre><code class="lang-js">export function transform(s: string): string { ... }
export * from &quot;./mod1&quot;;
export * from &quot;./mod2&quot;;
</code></pre>
<p><strong>Default Export</strong></p>
<div role="item"><p>export default声明是用来指定一个表达式的。这个表达式的内容会成为模块默认的输出内容：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">An export default declaration specifies an expression that becomes the default export of a module:
</p></div><pre><code class="lang-js">export default class Greeter {
    sayHello() {
        console.log(&quot;Greetings!&quot;);
    }
}
</code></pre>
<div role="item"><p>对应的，我们可以用default imports导入这些内容：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Which in tern can be imported using default imports:
</p></div><pre><code class="lang-js">import Greeter from &quot;./greeter&quot;;
var g = new Greeter();
g.sayHello();
</code></pre>
<p><strong>Bare Import</strong></p>
<div role="item"><p>我们可以用&quot;bare import&quot;导入一个模块，以获得导入这个模块时所带来的附加作用（side-effects）。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">A &quot;bare import&quot; can be used to import a module only for its side-effects.
</p></div><pre><code class="lang-js">import &quot;./polyfills&quot;;
</code></pre>
<div role="item"><p>你可以通过查阅ES6 module的支持说明来了解更多关于模块的信息。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">For more information about module, please see the ES6 module support spec.
</p></div><h2 class="section-title"><a name="声明和赋值时的解构" class="anchor" href="#声明和赋值时的解构"><span class="header-link"></span></a>声明和赋值时的解构</h2><div role="item"><p>TypeScript 1.5添加了对ES6中的解构声明和解构赋值（destructuring declarations and assignments）的支持。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">TypeScript 1.5 adds support to ES6 destructuring declarations and assignments.
</p></div><p><strong>声明</strong></p>
<div role="item"><p>解构声明会把从对象的属性（或数组的元素）中抽取出来的值，赋值给一个或多个变量。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">A destructuring declaration introduces one or more named variables and initializes them with values extracted from properties of an object or elements of an array.
</p></div><div role="item"><p>举例来说，下面的例子声明了x, y, z变量，并将他们的值分别初始化为getSomeObject().x，getSomeObject().y和getSomeObject().z。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">For example, the following sample declares variables x, y, and z, and initializes them to getSomeObject().x, getSomeObject().y and getSomeObject().z respectively:
</p></div><pre><code class="lang-js">var { x, y, z} = getSomeObject();
</code></pre>
<div role="item"><p>我们同样可以在数组上使用解构声明来抽取出数组中的值：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Destructuring declarations also works for extracting values from arrays:
</p></div><pre><code class="lang-js">var [x, y, z = 10] = getSomeArray();
</code></pre>
<div role="item"><p>同样的，解构也可以被用在函数参数的声明上：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Similarly, destructuring can be used in function parameter declarations:
</p></div><pre><code class="lang-js">function drawText({ text = &quot;&quot;, location: [x, y] = [0, 0], bold = false }) {  
    // Draw text  
}

// Call drawText with an object literal
var item = { text: &quot;someText&quot;, location: [1,2,3], style: &quot;italics&quot; };
drawText(item);
</code></pre>
<p><strong>赋值</strong></p>
<div role="item"><p>解构的模式也可以用在通常的赋值表达式上。举个例子，我们可以用一个解构赋值来实现交换两个变量的值：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Destructuring patterns can also be used in regular assignment expressions. For instance, swapping two variables can be written as a single destructuring assignment:
</p></div><pre><code class="lang-js">var x = 1;  
var y = 2;  
[x, y] = [y, x];
</code></pre>
<h2 class="section-title"><a name="支持<code>let</code>和<code>const</code>" class="anchor" href="#支持<code>let</code>和<code>const</code>"><span class="header-link"></span></a>支持<code>let</code>和<code>const</code></h2><div role="item"><p>现在我们也可以在ES3和ES5上使用<code>let</code>和<code>const</code>声明了。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">ES6 <code>let</code> and <code>const</code> declarations are now supported when targeting ES3 and ES5.
</p></div><p><strong>常量</strong></p>
<pre><code class="lang-js">const MAX = 100;

++MAX; // Error: The operand of an increment or decrement 
       //        operator cannot be a constant.
</code></pre>
<p><strong>块级作用域</strong></p>
<pre><code class="lang-js">if (true) {
  let a = 4;
  // use a
}
else {
  let a = &quot;string&quot;;
  // use a
}

alert(a); // Error: a is not defined in this scope
</code></pre>
<h2 class="section-title"><a name="支持for..of" class="anchor" href="#支持for..of"><span class="header-link"></span></a>支持for..of</h2><div role="item"><p>你现在可以在TypeScript 1.5的ES3/ES5数组上使用ES6 for..of循环了。同时它也完整支持ES6上的迭代器接口（Iterator interfaces）。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">TypeScript 1.5 adds support to ES6 for..of loops on arrays for ES3/ES5 as well as full support for Iterator interfaces when targetting ES6.
</p></div><p><strong>例子:</strong></p>
<div role="item"><p>当我们让TypeScript支持ES3/ES5时，编译器会将使用for..of的数组转换成我们惯用的ES3/ES5代码：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The TypeScript compiler will transpile for..of arrays to idiomatic ES3/ES5 JavaScript when targeting those versions:
</p></div><pre><code class="lang-js">for (var v of expr) { }
</code></pre>
<div role="item"><p>将会被转换成：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">will be emitted as:
</p></div><pre><code class="lang-js">for (var _i = 0, _a = expr; _i &lt; _a.length; _i++) {
    var v = _a[_i];
}
</code></pre>
<h2 class="section-title"><a name="装饰器(Decorators)" class="anchor" href="#装饰器(Decorators)"><span class="header-link"></span></a>装饰器(Decorators)</h2><div role="item"><p>TypeScript装饰器（decorator）是基于ES7的装饰器提案实现的。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">TypeScript decorator is based on the ES7 decorator proposal.
</p></div><div role="item"><p>装饰器是：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">A decorator is:
</p></div><ul>
<div role="item"><p>一个表达式<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">an expression</p></div><div role="item"><p>它会作为一个函数执行<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">that evaluates to a function</p></div><div role="item"><p>它把目标，名称，属性描述（property descriptor）作为参数<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">that takes the target, name, and property descriptor as arguments</p></div><div role="item"><p>它可以返回一个属性描述，以作用在目标对象上<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">and optionally returns a property descriptor to install on the target object</p></div></ul>
<div role="item"><p>你可以查阅Decorators提案来获取更多信息。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">For more information, please see the Decorators proposal.
</p></div><p><strong>例子:</strong></p>
<div role="item"><p><code>readonly</code>和<code>enumerable(false)</code>这两个装饰器会在method属性被放置在类<code>C</code>上之前作用于method。装饰器会改变属性和方法的实现。比如在这个例子中，method的属性会被添加writable: false和enumerable: false两项属性描述。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Decorators <code>readonly</code> and <code>enumerable(false)</code> will be applied to the property method before it is installed on class <code>C</code>. This allows the decorator to change the implementation, and in this case, augment the descriptor to be writable: false and enumerable: false.
</p></div><pre><code class="lang-js">class C {
  @readonly
  @enumerable(false)
  method() { }
}

function readonly(target, key, descriptor) {
    descriptor.writable = false;
}

function enumerable(value) {
  return function (target, key, descriptor) {
     descriptor.enumerable = value;
  }
}
</code></pre>
<h2 class="section-title"><a name="动态计算的属性" class="anchor" href="#动态计算的属性"><span class="header-link"></span></a>动态计算的属性</h2><div role="item"><p>如果你想在初始化对象时给对象添加一些动态的属性的话，可能会碰上些小麻烦。举下面的例子来说：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Initializing an object with dynamic properties can be a bit of a burden. Take the following example:
</p></div><pre><code class="lang-js">type NeighborMap = { [name: string]: Node };
type Node = { name: string; neighbors: NeighborMap;}

function makeNode(name: string, initialNeighbor: Node): Node {
    var neighbors: NeighborMap = {};
    neighbors[initialNeighbor.name] = initialNeighbor;
    return { name: name, neighbors: neighbors };
}
</code></pre>
<div role="item"><p>我们需要先为neighbor-map创建一个对象变量，然后才能动态初始化它。在TypeScript 1.5中，我们可以让编译器替我们完成这类工作：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Here we need to create a variable to hold on to the neighbor-map so that we can initialize it. With TypeScript 1.5, we can let the compiler do the heavy lifting:
</p></div><pre><code class="lang-js">function makeNode(name: string, initialNeighbor: Node): Node {
    return {
        name: name,
        neighbors: {
            [initialNeighbor.name] = initialNeighbor
        }
    }
}
</code></pre>
<h2 class="section-title"><a name="字符串中的Unicode编码点转义" class="anchor" href="#字符串中的Unicode编码点转义"><span class="header-link"></span></a>字符串中的Unicode编码点转义</h2><div role="item"><p>ES6引入了escapes，使得用户仅需要使用一次escape就能表示一个Unicode编码点（codepoint）。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">ES6 introduces escapes that allow users to represent a Unicode codepoint using just a single escape.
</p></div><div role="item"><p>举例来说，假设我们需要转义一个包含UTF-16/UCS2字符&#39;𠮷&#39;的字符串。其中&#39;𠮷&#39;由一个代理对（surrogate pair）来表示，这就是说它是由一对16比特的编码单元——<code>0xD842</code>和<code>0xDFB7</code>来表示的。这意味着你必须转义<code>&quot;\uD842\uDFB7&quot;</code>，但实际上我们很难辨别这是两个独立的字符还是一个代理对。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">As an example, consider the need to escape a string that contains the character &#39;𠮷&#39;. In UTF-16/UCS2, &#39;𠮷&#39; is represented as a surrogate pair, meaning that it&#39;s encoded using a pair of 16-bit code units of values, specifically <code>0xD842</code> and <code>0xDFB7</code>. Previously this meant that you&#39;d have to escape the codepoint as <code>&quot;\uD842\uDFB7&quot;</code>. This has the major downside that it’s difficult to discern two independent characters from a surrogate pair.
</p></div><div role="item"><p>通过ES6的编码点转义，你可以通过像<code>&quot;\u{20bb7}&quot;</code>这样的转义来清楚地表达字符串或字符串模板中的字符表达的到底是什么。TypeScript会把这个字符串转换成ES3/ES5中的<code>&quot;\uD842\uDFB7&quot;</code>。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">With ES6’s codepoint escapes, you can cleanly represent that exact character in strings and template strings with a single escape: <code>&quot;\u{20bb7}&quot;</code>. TypeScript will emit the string in ES3/ES5 as <code>&quot;\uD842\uDFB7&quot;</code>.
</p></div><h2 class="section-title"><a name="在ES3/ES5中实现加标记的模板字符串" class="anchor" href="#在ES3/ES5中实现加标记的模板字符串"><span class="header-link"></span></a>在ES3/ES5中实现加标记的模板字符串</h2><div role="item"><p>在TypeScript 1.4中，我们添加了对字符串模板的支持（ES3/ES5/ES6），以及对ES6中的标记模板（tagged templates）的支持。这里要感谢@ivogabe为我们提供的一些深思熟虑的想法和工作，使得我们在ES3和ES5中也可以使用标记模板。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">In TypeScript 1.4, we added support for template strings for all targets, and tagged templates for just ES6. Thanks to some considerable work done by @ivogabe, we bridged the gap for for tagged templates in ES3 and ES5.
</p></div><div role="item"><p>当我们想要将代码转换成ES3/ES5时，下面的代码：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">When targeting ES3/ES5, the following code
</p></div><pre><code class="lang-js">function oddRawStrings(strs: TemplateStringsArray, n1, n2) {
    return strs.raw.filter((raw, index) =&gt; index % 2 === 1);
}

oddRawStrings `Hello \n${123} \t ${456}\n world`
</code></pre>
<div role="item"><p>会变成：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">will be emitted as
</p></div><pre><code class="lang-js">function oddRawStrings(strs, n1, n2) {
    return strs.raw.filter(function (raw, index) {
        return index % 2 === 1;
    });
}
(_a = [&quot;Hello \n&quot;, &quot; \t &quot;, &quot;\n world&quot;], _a.raw = [&quot;Hello \\n&quot;, &quot; \\t &quot;, &quot;\\n world&quot;], oddRawStrings(_a, 123, 456));
var _a;
</code></pre>
<h2 class="section-title"><a name="可选给AMD依赖添加名称" class="anchor" href="#可选给AMD依赖添加名称"><span class="header-link"></span></a>可选给AMD依赖添加名称</h2><div role="item"><p><code>/// &lt;amd-dependency path=&quot;x&quot; /&gt;</code>会告诉编译器，由于当前模块的调用，有一个非TS模块的依赖需要被注入。然而TS代码并不能使用这些代码。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori"><code>/// &lt;amd-dependency path=&quot;x&quot; /&gt;</code> informs the compiler about a non-TS module dependency that needs to be injected in the resulting module&#39;s require call; however, there was no way to consume this module in the TS code.
</p></div><div role="item"><p>而新添加的<code>amd-dependency name</code>属性则允许我们给一个amd依赖命名。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">The new <code>amd-dependency name</code> property allows passing an optional name for an amd-dependency:
</p></div><pre><code class="lang-js">/// &lt;amd-dependency path=&quot;legacy/moduleA&quot; name=&quot;moduleA&quot;/&gt;
declare var moduleA:MyType
moduleA.callStuff()
</code></pre>
<div role="item"><p>上面的代码生成的JS代码是：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Generated JS code:
</p></div><pre><code class="lang-js">define([&quot;require&quot;, &quot;exports&quot;, &quot;legacy/moduleA&quot;], function (require, exports, moduleA) {
    moduleA.callStuff()
});
</code></pre>
<h2 class="section-title"><a name="支持用tsconfig.json配置项目" class="anchor" href="#支持用tsconfig.json配置项目"><span class="header-link"></span></a>支持用tsconfig.json配置项目</h2><div role="item"><p>我们可以给一个文件夹添加一个<code>tsconfig.json</code>文件来表示当前文件夹是一个TypeScript项目的根目录。通过tsconfig.json，我们可以指定根文件（root files）以及编译选项。每个项目对会以下面的方式之一进行编译：<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Adding a <code>tsconfig.json</code> file in a directory indicates that the directory is the root of a TypeScript project. The tsconfig.json file specifies the root files and the compiler options required to compile the project. A project is compiled in one of the following ways:
</p></div><ul>
<div role="item"><p>如果我们使用tsc指令但是不指定输入文件，编译器会就会从当前文件夹开始，向上寻找tsconfig.json文件。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">By invoking tsc with no input files, in which case the compiler searches for the tsconfig.json file starting in the current directory and continuing up the parent directory chain.</p></div><div role="item"><p>如果我们使用tsc指令但是不指定输入文件，那我们可以使用-project（或 -p）命令行选项来指定包含tsconfig.json文件的文件夹。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">By invoking tsc with no input files and a -project (or just -p) command line option that specifies the path of a directory containing a tsconfig.json file.</p></div></ul>
<p><strong>例子:</strong></p>
<pre><code class="lang-js">{
    &quot;compilerOptions&quot;: {
        &quot;module&quot;: &quot;commonjs&quot;,
        &quot;noImplicitAny&quot;: true,
        &quot;sourceMap&quot;: true,
    }
}
</code></pre>
<div role="item"><p>你可以查看tsconfig.json的维基页面获取详细信息。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">See the tsconfig.json wiki page for more details.
</p></div><h2 class="section-title"><a name="<code>--rootDir</code>命令行" class="anchor" href="#<code>--rootDir</code>命令行"><span class="header-link"></span></a><code>--rootDir</code>命令行</h2><div role="item"><p>在进行输出文件时使用<code>--outDir</code>选项会根据输入文件的路径结构来进行。编译器会以根目录下的文件的路径作为所有输入文件的最长路径截点（即路径不会超过根目录），使用每个输入文件的路径来放置输出文件。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Option <code>--outDir</code> duplicates the input hierarchy in the output. The compiler computes the root of the input files as the longest common path of all input files; and then uses that to replicate all its substructure in the output.
</p></div><div role="item"><p>但有时候我们并不希望这样。比如我们输入<code>FolderA\FolderB\1.ts</code>和<code>FolderA\FolderB\2.ts</code>，则输出文件都会出现在一个<code>FolderA\FolderB\</code>这样的镜像结构的文件中。如果我们再增加一个<code>FolderA\3.ts</code>作为输入文件，则这个文件对应的输出文件就会出现在一个<code>FolderA\</code>文件中。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori">Sometimes this is not desirable, for instance inputs <code>FolderA\FolderB\1.ts</code> and <code>FolderA\FolderB\2.ts</code> would result in output structure mirroring <code>FolderA\FolderB\</code>. now if a new file <code>FolderA\3.ts</code> is added to the input, the output structure will pop out to mirror <code>FolderA\</code>.
</p></div><div role="item"><p>而<code>--rootDir</code>允许我们指定那些输出时，其路径要被镜像的文件夹，来代替计算输出路径。<span class="check-ori" role="check-ori">[原文]</span></p><p role="ori" class="ori"><code>--rootDir</code> specifies the input directory to be mirrored in output instead of computing it.
</p></div><hr>
